大神勿喷哈!
闲来没事看了一下ctf,发现谖草利用注入爆破第二题的思路!于是自己也想写个程序注入爆破,但是发现其中还是有诸多的问题。首先CM和你注入的程序是相互独立运行的,解密函数运行的时候你不能改变输入其中的值(栈中的数据)。比如:当CM中的程序判断输入的"10000000\n"是否正确时,注入程序突然就将数据"10000001\n"注入进CM,这样肯定是不对的。所以我们判断什么时候解密程序解密完成!这里我提供的思想就是让其成为如同操作系统中的临界资源区,首先设置一个标志lock当lock=1时解密函数解密完成可以注入,当lock=0时候函数正在解密不可注入。
下面就是找到CM解密位置所在,载入IDA与OD发现用fgets将输入数据放入v19中,仔细查看程序发现27到87行是解密的关键,爆破思路:修改程序让其在27到87行循环。
这下就又遇到问题,如何修改。载入OD找fgets()单步走一步就发现输入的字符串在栈中0x0012BE54 的位置这里就是我们的注入点 而设置的lock标志在0x0012BE84,为什么选这个位置因为V19分配了260个空间完全够用。
修改程序需要注意的是堆栈平衡,不然程序就会报错!像在下面的修改就直接加了个sub esp,0x18就是为了平衡。下面那个jmp是为了跳到修改lock的地方。
下面就是最上面那个图的小的循环圈
还有最好把打印错误的程序也给修改了为了提高爆破速度。到此CM修改完毕。轮到注入程序了。
LPCVOID pbase = (LPCVOID)0x0012BE94;
DWORD dwtmp;
//dwtmp=pbase;
DWORD base_1=0x0012BE54;
DWORD lock=0x0012BE94;
//char buf[4] = { 0 };
char buf[4]={0};
DWORD dwRead;
while (TRUE){
if(!::ReadProcessMemory(game_handle,pbase,&dwtmp,4,&dwRead)){
printf("error to read mem!\n");
}
tm=0;
if(dwtmp==1){
ltoa(count, test, 10);
while(test[tm]!='\0'){
tm++;
}
test[tm]=10; // 10=0A='\n'
if(!WriteProcessMemory(game_handle,(LPCVOID *)base_1, test, 16, &dwRead)){
printf("error to write mem!\n");
}
if(!WriteProcessMemory(game_handle,(LPCVOID *)lock,buf, 4, &dwRead)){
printf("error to write mem!\n");
}
count++;
}
//WriteProcessMemory(game_handle,pbase, buf, 4, &dwRead);
}
需要注意的就是在后面加上0A='\n'因为解密需要。不过最坑的是发现跑了很久跑到1000100000左右,只跑10万左右因为程序输入8-20为的数字才有效。所以从10000000开始.
看下大神的key 是97654321 实在忍受不了等那么久想验证程序是否成功就把count改为97600000.过了一会儿发现中断了下来。嗨 还成功了!虽然没从10000000开始,但是还是有种成功的感觉!大神可以无视哈。
[课程]Android-CTF解题方法汇总!
最后于 2018-3-6 20:29
被大帅锅编辑
,原因: