问题已经自己解决.... 稍后整理成个心得帖吧 也算是一种成长!
1.我想做什么;
因为不知道涉及到的具体的学术名词,姑且就结合我自身实际情况解释下.
我们学破解,我们学外挂(不仅是游戏)无非就是对技术的一种不同运用而已,而在这条路上没有一条光明的指路灯,很欣喜的找到看雪这个宝地,能够自由的汲取知识... ... 而且被这里的氛围所感动,为了不玷污这块天堂,我一般尽量少提问,觉的事情应该自己解决,还有就怕别人指着鼻子骂,说你连这个都不会自己思考,还妄想研究破解,外挂..... 我不是怕骂我自己,而是不想让这个技术的殿堂蒙诟!
我注册看雪的时间不长,但是我一步一步从看雪这里知道了好多好多以前不知道的新名词,了解了好多好多的新知识,并凭着兴趣和毅力一直向前努力着!如果把看雪比作一座宝藏,那么一个在宝藏中指引方向的人,对于我来说无疑最是弥足珍贵的...
好了,大家的时间都很宝贵,无论怎样,技术无罪!
我要做的事情就是 "游戏找CALL练习实例ONE",这个网上能找到的最普遍的外挂入门练手程序,达到效果是 1.我自己写个DLL 注入后 能够直接调用加血CALL....
2.继续研究,我想在这个加血CALL上做点手脚,比如我调用后 执行到我自己的函数(比如弹出个对话框等等),这个函数的功能是写日志(我自己的理解是比较接近inline hook 但是不知道对不对).然后再让程序跳回去执行!
2.我如何做的;
1.环境 OD VC++2008 断点bp send
2.找到加血CALL地址,地址在 0x00452e98(不同电脑位置一样,寄存器值不一样,无参调用),编程dll,注入调用,无错,通过!
程序代码:
void MyDialog::OnBnClickedButton1()
{
MessageBox("开始吃血","开始吃血",0);
_asm{
pushad;
mov eax, 0x00991f84;
mov ecx, 0x0042abe4;
mov edx, 0x00453028;
mov ebx, 0x00452e98;
call ebx;
popad;
}
MessageBox("吃血成功","吃血成功",0);
}
2.在00452e98处修改该内存,前7个字节,由于字节对齐和保持指令完整,实际上要覆盖掉10个字节...
源代码效果:
[COLOR="Blue"]00452E98 55 push ebp
00452E99 8BEC mov ebp,esp
00452E9B 83C4 F8 add esp,-8
00452E9E 53 push ebx
00452E9F 8955 FC mov dword ptr ss:[ebp-4],edx[/COLOR]00452EA2 |. 8BD8 mov ebx,eax
00452EA4 |. 8B45 FC mov eax,[local.1]
00452EA7 |. E8 1414FBFF call 游戏找CA.004042C0
00452EAC |. 33C0 xor eax,eax
00452EAE |. 55 push ebp
00452EAF |. 68 7E2F4500 push 游戏找CA.00452F7E
00452EB4 |. 64:FF30 push dword ptr fs:[eax]
00452EB7 |. 64:8920 mov dword ptr fs:[eax],esp
00452EBA |. 8B45 FC mov eax,[local.1]
00452EBD |. BA 942F4500 mov edx,游戏找CA.00452F94
00452EC2 |. E8 5513FBFF call 游戏找CA.0040421C
00452EC7 |. 75 2B jnz short 游戏找CA.00452EF4
实际执行效果:
功能代码:
void MyDialog::OnBnClickedButton3()
{
MEMORY_BASIC_INFORMATION mbi;
/*** 保存要修改地址的原有的属性信息 ***/
DWORD dwProtect;
/*** 查询要修改地址的属性 ***/
if( !VirtualQuery((void *)0x0041E800, &mbi, sizeof(MEMORY_BASIC_INFORMATION)))
if( !VirtualQuery((void *)0x006EEE00, &mbi, sizeof(MEMORY_BASIC_INFORMATION)))
return;
/*** 修改要悠地址的属性,主要目的在于去掉只读保护 ***/
if( !VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &dwProtect))
return;
/*** 修改游戏中的指令,使其跳转到我们的函数 ***/
//直接修改的地址
*((BYTE *)(0x00452e98)) = (BYTE)(0xB8);
*((DWORD *)(0x00452e99)) = (DWORD)(MyTest);
*((BYTE *)(0x00452e9d)) = (BYTE)(0xFF);
*((BYTE *)(0x00452e9e)) = (BYTE)(0xE0);
*((BYTE *)(0x00452e9f)) = (BYTE)(0x90);
*((BYTE *)(0x00452ea0)) = (BYTE)(0x90);
*((BYTE *)(0x00452ea1)) = (BYTE)(0x90);
///////////////////////////////////////////////////
/*asm{
mov esi,0x452e98
mov byte ptr [esi],b8
inc esi
mov esi,MyTest
add esi,4
mov word ptr [esi],0x0EFF
add esi,2
}*/
if(!VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READ, &dwProtect))
return;
}
我的TEST函数
void _stdcall MyTest(){ //[COLOR="red"]其实这个函数一进来就在堆栈里申请了一大块空间[/COLOR]
_asm{
pushad
pushfd
call MyTestGUI
popfd
popad
//为了补全前面丢失的代码
//add esp,0x1C [COLOR="Red"]在这如何恢复堆栈[/COLOR]
push ebp
mov ebp,esp
add esp,-8
push ebx
mov dword ptr ss:[ebp-4],edx
mov eax,0x00452EA2 //计划跳回去
jmp eax
}
}
void _stdcall MyTestGUI(){
//MessageBox(NULL,"MyTestForRun", "Test",0);
::AfxMessageBox ("我被执行啦啦啦啦");
}
哪些原因被我基本排除了;
错误出在自己函数执行完毕返回目标程序的时候(能够执行完我写的对话框,然后回到主程序的时候再F8几步就出错).......个人认为是堆栈平衡的问题...
但是 ....我在看雪上找资料大多难以有效解决问题,一些基础还是一团浆糊...
不知道我理解的对不对 请各位指点下堆栈计算的资料.... 比如我知道PUSH 一个单字 esp-2
push一个双字 esp-4
那么pushad pushfd呢?
目标程序
游戏找CALL练习实例one.rar
[课程]Android-CTF解题方法汇总!