接上篇(PWN学习001):http://www.secist.com/archives/3597.html
找到第二个,直接开始,第一篇说清楚了前奏。
首先ssh连接到对方服务器。
尝试执行./col这个程序,查看结果。
查看源码col.c:
#include <stdio.h> #include <string.h> unsigned long hashcode = 0x21DD09EC; unsigned long check_password(const char* p) { int* ip = (int*)p; int i; int res=0; for(i=0; i<5; i++) { res += ip[i]; } return res; } int main(int argc, char* argv[]) { if(argc<2) { printf("usage : %s [passcode]\n", argv[0]); return 0; } if(strlen(argv[1]) != 20) { printf("passcode length should be 20 bytes\n"); return 0; } if(hashcode == check_password( argv[1] )) { system("/bin/cat flag"); return 0; } else printf("wrong passcode.\n"); return 0; }
可以看到需要输入20个字符,如果输入了20个字符,就进入check_password()函数,进行校验密码,我们仔细看看这个函数。
unsigned long check_password(const char* p) { int* ip = (int*)p; int i; int res=0; for(i=0; i<5; i++) { res += ip[i]; } return res; }
这个函数,将传进来的那20个字符p,进行(int *)强制转换也就是会把这20个分成4 个char类型为一组,一共分5组,因为char 是 1个字节,所以4个为一组,一共5组,刚好20个字节,刚好20个输入字符串。
然后把每四个字符看成一共int型的数字,进行5次循环相加,结果放入res中。
然后分析函数入栈情况。
因为:
unsigned long hashcode = 0x21DD09EC;
所以,只要让我们的输入字符串四个一组加起来等于0x21DD09EC就可以啦!所以没有确定的值,只要符合即可!
先用0x21DD09EC减去一个简单的值,例如:0x10101010 乘以 4 等于 0xE19CC9AC。
执行 代码 :./col $(python -c “print ‘\xAC\xC9\x9C\xE1’+’\x10’ * 16”) ?注意:必须是小端格式。
十六个’\x10′ 加上 ?0xE19CC9AC 刚好是 0x21DD09EC,所以利用成功!