一道整数相关的题~
opm
分析
保护全开,GOT可劫持:
1 2 3 4 5 6 7 8
| ➜ Desktop checksec opm [*] '/root/Desktop/opm' Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled ➜ Desktop
|
分析有一个结构体表示role:
1 2 3 4 5 6 7 8 9 10 11
| 00000000 role struc ; (sizeof=0x28, mappedto_6) 00000000 fpOutSlogan dq ? ; offset 00000008 nameP dq ? ; offset 00000010 nameLen dq ? 00000018 punchs dd ? 0000001C db ? ; undefined 0000001D db ? ; undefined 0000001E db ? ; undefined 0000001F db ? ; undefined 00000020 field_20 dq ? 00000028 role ends
|
有两个功能,添加:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| struct role *add() { struct role *tmpRole; // rbx struct role *tmpRole3; // rbx size_t nameLen; // rax struct role *tmpRole4; // rbx char buf[128]; // [rsp+0h] [rbp-1A0h] struct role *tmpRole2; // [rsp+80h] [rbp-120h] char *name; // [rsp+100h] [rbp-A0h] struct role *v8; // [rsp+188h] [rbp-18h]
v8 = (struct role *)__readfsqword(0x28u); tmpRole = (struct role *)operator new(0x20uLL); initRole(tmpRole); tmpRole2 = tmpRole; tmpRole->fpOutSlogan = outSlogan; puts("Your name:"); gets(buf); tmpRole3 = tmpRole2; tmpRole3->nameLen = strlen(buf); nameLen = strlen(buf); name = (char *)malloc(nameLen); strcpy(name, buf); tmpRole2->nameP = name; puts("N punch?"); gets(buf); tmpRole4 = tmpRole2; tmpRole4->punchs = atoi(buf); outSlogan(tmpRole2); return tmpRole2; }
|
此处有两个明显的栈溢出,但是由于有canary和pie不能直接覆写返回地址,buf之上有两个指针,能控制tmpRole2
它指向role,于是可以对其进行一些控制,在添加结束程序会输出两个域,其中punchs是用户输入没什么用,但是nameP域是可控的,可以用来泄露数据:
1 2 3 4
| int __fastcall outSlogan(struct role *a1) { return printf("<%s> said he can kill the boss with %lx punches\n", a1->nameP, a1->punchs); }
|
而show函数是直接使用role结构体里的函数指针:
1 2
| for ( i = totalRoles - 1; i >= 0; --i ) ((void (__fastcall *)(struct role *, char *))roleList[i]->fpOutSlogan)(roleList[i], &buf);
|
利用
综上,我们的思路就是先泄露出堆地址与opm程序的地址,有这两个东西,就能控制堆进一步通过读取GOT泄露出libc地址,再试试onegadget什么的,妙呀~
- 对堆进行排布,使下次分配时,nameP之前的位置低字节为’\x00’,这样就可以使用部分覆盖改写
//add一个role,在输入punchs处将tmpRole2指向前移25Bytes处,改写nameP使其指向它自身,此时就会输出堆地址
- add一个role,在输入punchs处将tmpRole2指向前移25Bytes处,改写nameP使其指向它自身前移8Bytes处,此时就会输出slogan地址
- add一个role,在输入punchs处将tmpRole2指向gets@got.plt-8处,改写无用位置,此时就会输出libc的地址
- add一个role,在输入punchs处将tmpRole2指向atoi@got.plt-24处,改写atoi为system
- add一个role,在输入punchs处输入’/bin/sh\0’getshell
结果