吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 40225|回复: 297
收起左侧

[原创] 从零开始教你做辅助(一)

    [复制链接]
shanlihou 发表于 2021-1-30 18:04
大家好,我是山里猴,上次发了篇经验分享的帖子后,有些朋友说能不能做一个从零开始的系列.
承蒙大家厚爱,小弟受宠若惊,哈哈,从零开始系列来了.
说到怎么做好一个辅助啊,这我非常有经验,辅助最重要的就是,对线期一定不要跟大哥抢钱,大哥上去送的时候一定要及时加血,并用自己伟岸的身躯给大哥挡伤害.
!!!不对,这里是吾爱论坛啊,不好意思,走错片场了,下面回归正题.
本期内容先讲下怎么从目标程序中获取怪物信息.
这期内容的markdown我也会同步放到我的gayhub项目中的https://github.com/shanlihou/hack_warspear,的tutorial文件夹下面

获取怪物信息

0x01:工具及背景知识

1.cheat engine

ce查内存神器,还能调试

2.IDA

查看反汇编静态代码用的

3.immunity debugger

查看代码或者调试都很有用

4.语言(c++,python,lua,汇编)

c++:用来编写辅助程序
python:用来在immunity debugger中编写插件
lua:用来在ce中编写插件
汇编:能看懂就行,不要求会写,逆向程序逻辑时候需要

0x02:找到修改血量代码位置

首先找到怪物的血量地址,如下图.

find_hp
如上图所示,按照上图位置右键"找出是什么改写了这个位置",并点击附加到进程.
在附加到进程后攻击这个怪物.这时候会看到下图
opr_addr
图中地址00570FFB就是修改怪物血量的代码位置

0x03:找到调用堆栈

还记得我们上次讲怎么用ce+lua吗.
我们编写如下脚本
代码位置:$(ROOT)/info/find_hp_base.lua

function print_stack(ebp, deep) --打印堆栈的函数,返回值是堆栈调用过程
    if deep == 0
    then
        return ""
    end
    local ebp_4 = readInteger(ebp + 4)
    local str_ret = string.format("%x->", ebp_4)
    local next_ebp = readInteger(ebp)
    str_ret = str_ret .. print_stack(next_ebp, deep - 1)
    return str_ret
end

function clear_debug() --清除所有已经添加的断点
    local tbl = debug_getBreakpointList()
    if tbl == nil
    then
        return
    end
    for i,v in ipairs(tbl) do
        print(string.format("%4d 0x%X",i,v))
        debug_removeBreakpoint(v)
    end
end

function debugger_onBreakpoint() --默认断点函数
    if EIP == 0x570FFB -- 这个位置是咱们刚刚获得的修改怪物血量的代码位置
    then
        local ret = print_stack(EBP, 10)
        print(ret)
    else
        print("not found")
    end
    return 1
end

clear_debug()
debug_setBreakpoint(0x570FFB)

好,我们现在拿着如上代码在ce上执行.执行完后,就可以操作玩家打怪了.
在玩家攻击后会看到如下图打印

attack_stack

上图中红框框出来的这个打印就是一次扣血的调用过程,我们就拿着这个找基址
70e76a->70fa54->747e0e->87c579->86052b->75b247ab->75b02aac->75b044db->75b041e0->8602c6->

0x04:找到基址

现在用immunity debugger打开我们的游戏并定位到位置0x570FFB

find_base

我们从上图1位置(0x570FFB)可以看出血量应该是保存在esi+0xf4这个位置,那么我们现在就要找esi的值是怎么来的
我们网上看图2位置(0x570ff2)esi是从eax赋值的,那么就要找eax怎么来的.
在网上看图3位置有一个函数调用,一般汇编的函数如果有返回值的话是保存在eax的.所以我们要跟进去看是不是这个函数返回的.

btree

上图是进入函数0x715720后,的相关内容,我给大家翻译一下上面的内容,下面是翻译后的c++代码.

```c++
eax = (ecx + 0x30);
eax =
(eax);
edx = (ebp + 0x8);
while (1):
{
ecx =
(eax + 0x10);// MOV ECX,DWORD PTR DS:[EAX+10]
if (ecx > edx){//CMP ECX,EDX;    JBE SHORT warspear.0071573C
eax = (eax + 0x4);
continue;
}
else if (exc < edx){//JNB SHORT warspear.0071574B
eax =
(eax + 0x8);
continue;
}
else{
eax = *(eax + 0x14);
break;
}
}


有一定c/c++语言功底的朋友不难看出,上面代码是一段对数据结构二叉树的查找过程.所以我们可以确定了,这款游戏的怪物信息是使用二叉树来存储的.  
把上图的eax想象成一个节点.那么eax+0x10这个位置存储的就可能是类似id的值,然后跟edx这个目标值来比较.  
如果当前id > edx 则从右节点继续找(eax + 0x04)
如果当前id < edx 则从左节点继续找(eax + 0x08)
如果相等就用eax = *(eax + 0x14)然后返回.

所以从上图汇编代码我们得到三个信息:  
1.a的确是返回值  
2.怪物信息存在一个二叉树里  
3.从第一行(MOV EAX,DWORD PTR DS:[ECX+38])看出,咱门下一个追踪目标就是这个ecx了

我们继续顺着上面汇编图的4,5,6会发现我们已经找到了基址(哈哈,很尴尬,前面的查看堆栈貌似没啥用啊,没关系,下次讲一定会把它用上的.因为我之前完成的时候已经过去很久了,写这篇文章时候是边做边写的.所以没想到没用上)  
从"MOV EAX,DWORD PTR DS:[9A45B0]" 中得到基址 0x9A45B0

## 0x05:测试基址是否正确

我们编写如下lua代码  
代码位置:$(ROOT)/info/print_tree.lua

```lua
function handleNode(value, ptr, hp)
    print(string.format('%x,%x,%d', value, ptr, hp))
end

function read_tree(node, func)--读取二叉树结构体的代码
    if (node == 0 or node == nil)
    then
        return
    end

    local left = readInteger(node + 4)
    local right = readInteger(node + 8)
    local value = readInteger(node + 0x10)
    local ptr = readInteger(node + 0x14)
    local hp = readInteger(ptr + 0xf4) --这里存的就是血量了.对应上面汇编代码中的(esi + f4)
    read_tree(left, func)
    read_tree(right, func)
    func(value, ptr, hp)
end

local g_base = readInteger(0x9a45b0)
local tmp_ptr = readInteger(g_base + 0x10)
tmp_ptr = readInteger(tmp_ptr + 0x38)
local root = readInteger(tmp_ptr)
read_tree(root, handleNode)

把上面代码放在ce中执行就会看到打印如下

my_hp

上图中1已经把我自己的hp打印出来了.可以看出这个基址是没有问题的.

0x06:写我们的辅助程序

好了现在完事具备,只欠东风,下面就开始写我们的辅助程序.
cpp_code

如图是用vs2019打开工程后的目录结构.
图上标号1位置这个工程是辅助逻辑相关,比如查看怪物信息,攻击怪物,捡去物品等,这个最后生成了一个静态库
图上标号2位置这个工程是注入后的主进程,最后编译为一个动态库.(实际上1和2可以合并一起,因为2在运行过程中调用gameData工程里的接口,所以把gameData静态链接进2)
图上标号3位置这个工程是用来把上面编写的动态库注入到目标程序中用的.  

下面我们就其中一些重要并在本章节用到的代码讲解一下

1.注入过程

代码位置:$(ROOT)/InjectDll/InjectDll.cpp

```c++
warHandle = FindWindowA(GAME_CLASS_NAME, NULL);//根据窗口名字找到目标进程的窗口句柄
if (warHandle == 0)
return;

printf("find handle\n");
GetWindowThreadProcessId(warHandle, &pid); // 根据目标句柄获取目标主进程pid
if (pid == 0)
{
    printf("get pid error\n");
    return;
}

hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); // 获取目标进程句柄,并获取所有操作权限
if (hProcess == NULL)
{
    printf("get hProcess error\n");
    return;
}

addressDW = (LPDWORD)VirtualAllocEx(hProcess, NULL, 256, MEM_COMMIT, PAGE_READWRITE);
//在目标进程内申请一段内存,主要用来存放即将被我们注入的动态库的全路径
if (addressDW == NULL)
{
    printf("get hProcess error\n");
    return;
}

WriteProcessMemory(hProcess, addressDW, dllPath, strlen(dllPath) + 1, &byWriteSize);
//将动态库全路径保存到刚刚申请的内存里
if (byWriteSize < strlen(dllPath))
{
    printf("write memmory failed!");
    return;
}

threadHandle = CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibraryA, addressDW, NULL, NULL);
//在目标进程内创建线程线程,线程会执行加载动态库的操作
WaitForSingleObject(threadHandle, 0xFFFFFFFF);
//等待刚刚加载动态库操作完成,好了,到此,我们的注入操作完成.
CloseHandle(threadHandle);
VirtualFreeEx(hProcess, addressDW, 256, MEM_COMMIT);
CloseHandle(hProcess);

### 2.注入后的主函数

代码位置:$(ROOT)/GameData/HookGameMainThread.cpp

```c++
LRESULT CALLBACK GameWndProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    CWPSTRUCT* lpArg = (CWPSTRUCT*)lParam;
    if (nCode == HC_ACTION)
    {
        if (lpArg->hwnd == getGameWndHandle() && lpArg->message == g_myMsgCode)
        {
            // 注入后的ui线程会给主线程发消息,消息被钩子在这里截获,截获后,根据消息类型执行相关操作
            doAction((MsgAction)lpArg->wParam);
            return 1;
        }
    }

    return CallNextHookEx(g_hhkGame, nCode, wParam, lParam);
}

DWORD HookMainThread() //注入后的主函数其实会实例化一个ui窗口,然后再窗口主进程里执行这个函数
{
    log_debug("hook ok\n");
    HWND hGame = getGameWndHandle(); // 获取主线程窗口句柄,这个要通过ce实现查找主线程句柄存放基址
    DWORD ndThreadId = GetWindowThreadProcessId(hGame, NULL); // 根据主线程句柄获取主线程id
    if (ndThreadId == NULL)
    {
        return 1;
    }

    g_hhkGame = SetWindowsHookExA(WH_CALLWNDPROC, GameWndProc, NULL, ndThreadId);
    // 注册一个钩子函数到主线程中,钩子函数为上面的GameWndProc
    return 1;
}

最终效果如下图所示:
final

大家会看到,多了一个图标和我们目标进程一样,名字叫Dialog的窗口,这个就是注入后的UI线程.
点击窗口中的test按钮,会给主线程发送一个MsgTest的消息,主线程中收到消息后会把怪物信息输出到e:\shlog\warspear.log里面(这个位置是写死的,大家可以在GameData/debug.h文件里修改)
可以看到,日志输出和我们在ce里面看到的是一样的,到此,我们的获取怪物信息就ok了.
大家有什么不明白,欢迎给我提issue.

免费评分

参与人数 140威望 +2 吾爱币 +222 热心值 +128 收起 理由
阳霆贾不假 + 1 + 1 谢谢@Thanks!
zj2018 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
永驻的青春 + 1 + 1 用心讨论,共获提升!
shen54188 + 1 + 1 谢谢@Thanks!
机械诅咒 + 1 + 1 用心讨论,共获提升!
guweijia + 1 + 1 用心讨论,共获提升!
小马奔腾2 + 1 热心回复!
呆呆♂DD + 1 + 1 谢谢@Thanks!
Vchan + 1 + 1 谢谢@Thanks!虽然看了一遍但还是没跟上,但不妨碍献上币
甲申侯 + 1 + 1 谢谢@Thanks!可我还是看懵了
vanillasky0220 + 1 + 1 热心回复!
lzwdwyy + 1 + 1 用心讨论,共获提升!
Lomenot + 1 + 1 用心讨论,共获提升!
12138chen + 1 + 1 谢谢@Thanks!
alanorpeggy + 1 + 1 谢谢@Thanks!
山上雪云间月 + 1 + 1 我很赞同!
1晨光1 + 1 谢谢@Thanks!
happya99baby + 1 + 1 我很赞同!
wxc941112 + 1 + 1 热心回复!
007neko + 1 谢谢@Thanks!
rekaytang + 1 + 1 我很赞同!
shudong2021 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
ALCATEL + 1 + 1 谢谢@Thanks!
-安桉- + 1 谢谢@Thanks!
徐景行 + 1 + 1 我很赞同!
不知道怎么办 + 1 我很赞同!
CXC303 + 1 谢谢@Thanks!
0Dog + 1 + 1 很棒!
ma4907758 + 1 + 1 谢谢@Thanks!
hett123456 + 1 + 1 我很赞同!
JKtoMars + 1 + 1 谢谢@Thanks!
w504042696 + 1 + 1 感谢您的宝贵建议,我们会努力争取做得更好!
一团哈欠 + 1 + 1 我很赞同!
李牧之 + 1 + 1 我很赞同!
bsjonline + 1 + 1 谢谢@Thanks!
xycg529 + 1 + 1 谢谢@Thanks!
18030900400 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
过火清高 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
qi2001127 + 1 + 1 感谢大佬
xzf1990 + 1 谢谢@Thanks!
尺间萤火 + 1 + 1 鼓励转贴优秀软件安全工具和文档!
Zhaowouk + 1 + 1 谢谢@Thanks!
人各有志Q + 1 + 1 谢谢@Thanks!
Schizoo + 1 + 1 谢谢@Thanks!
a278962 + 1 我很赞同!
A37 + 1 + 1 谢谢@Thanks!
yRiven + 1 + 1 谢谢@Thanks!
听雨轩灬烟雨 + 1 我很赞同!
wangzhenj + 1 + 1 我很赞同!
lucasmonster + 1 谢谢@Thanks!
By:虚假 + 1 + 1 谢谢@Thanks!
爆炎 + 1 + 1 谢谢@Thanks!
咸鱼的征程 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
淡灬看夏丶恋雨 + 1 + 1 我很赞同!
朕来打江山 + 1 + 1 很有收获
cccluck + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
lichaojingming + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Caviar + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
csotour + 1 + 1 我很赞同!
Maise + 1 我很赞同!
ZeroStart + 1 + 1 我很赞同!
g673070689 + 1 + 1 我很赞同!
culushishui + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
yanmimi + 1 + 1 我很赞同!
life091303 + 1 + 1 鼓励转贴优秀软件安全工具和文档!
明亮的夜空 + 1 + 1 谢谢@Thanks!
Sasuke丶轮回 + 1 我很赞同!
Xiao_xiao_ye + 1 热心回复!
quize01 + 1 + 1 虽然后面看蒙了,但一样要支持
titaz + 1 + 1 谢谢@Thanks!
sym945 + 1 + 1 热心回复!
又飘小雪 + 1 + 1 我很赞同!
幻想世界hxsj + 1 + 1 我很赞同!
sdogboy + 1 + 1 谢谢@Thanks!
iamshy520 + 1 + 1 用心讨论,共获提升!
火神猎杀者 + 1 我很TM赞同!
qcinnovative + 1 + 1
sansi + 1 + 1 我很赞同!
hiel + 1 + 1 我很赞同!
erebusx + 1 我很赞同!
showzonezhu + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
sinnvg + 1 + 1 谢谢@Thanks!
wenrow + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
qaz6897419 + 1 + 1 热心回复!
hyprince33 + 1 + 1 谢谢@Thanks!
wtlone001 + 1 + 1 谢谢@Thanks!
DoraeM + 1 + 1 很棒
qiaoyong + 1 + 1 热心回复!
gaosld + 1 + 1 谢谢@Thanks!
参数 + 1 + 1 用心讨论,共获提升!
By阿清 + 1 + 1 我很赞同!
UseLess + 1 谢谢@Thanks!
aaafff + 1 谢谢@Thanks!
603704193 + 1 + 1 我很赞同!
w2pj123 + 1 + 1 用心讨论,共获提升!
sunrainnet + 1 + 1 谢谢@Thanks!
九重桂妖 + 1 我很赞同!
a261201 + 1 + 1 我很赞同!
寻觅背影 + 1 + 1 热心回复!
wangzihang + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

zl20110000 发表于 2021-1-30 23:12
开局就是地狱难度
moliy 发表于 2021-1-30 23:46
周小雨 发表于 2021-2-6 10:48
还记得14年看的某辅助作者制作植物大战僵尸...
用的易语言加CE
去用动态基址算静态基址然后用易语言加了个独写内存的功能的模块然后就巴拉的一下的就做出来,整的不明不白~~
您这个就显得逻辑上很通顺!
qzhsjz 发表于 2021-1-30 21:21
楼主,我想请教一下,这个论坛的markdown是不是大标题有bug啊?需要用二级标题才能正常显示?
 楼主| shanlihou 发表于 2021-1-31 10:25
ghoob321 发表于 2021-1-31 08:55
能用python写辅助吗

纯python估计不行的,需要调用一些c++封装的接口,但是可以大部分逻辑用python
 楼主| shanlihou 发表于 2021-1-30 21:25
qzhsjz 发表于 2021-1-30 21:21
楼主,我想请教一下,这个论坛的markdown是不是大标题有bug啊?需要用二级标题才能正常显示?

好像显示没啥问题,",获取怪物信息"就是我的大标题
630216608 发表于 2021-1-30 21:29
牛比呀!!!!
幻—— 发表于 2021-1-30 22:55
插点学习;哦
wolfdada 发表于 2021-1-31 00:53
谢谢大佬分享知识,受教
ee029384756 发表于 2021-1-31 02:19
你只以为我在第一层 其实我在地下十八层
但是大佬确实牛逼
traviswen 发表于 2021-1-31 03:43
学习总是在不断进步中潜移默化了
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-23 02:47

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表