设为首页收藏本站 今天是: 2024-02-27    美好的一天,从现在开始

复仇者黑客组织

 找回密码
 立即注册

QQ登录

只需一步,快速开始

    查看: 932|回复: 6

    手把手教你让EXE调用自己写的DLL函数实增加功能

    [复制链接]

    该用户从未签到

    46

    主题

    46

    帖子

    148

    积分

    审核员

    Rank: 7Rank: 7Rank: 7

    积分
    148
    发表于 2023-12-8 12:09:38 | 显示全部楼层 |阅读模式
    新手第一次写逆向和改造的过程,难免有错误或走弯路的地方,请大神们多多指正。
    本文旨在探讨程序编写技术,相关程序均为自已编写代码测试,请勿用于非法目的。

    【情境介绍】注:为避免引起歧义,以下为虚拟情境,如有雷同,纯属巧合。



    最近拿到某办公程序(x86):victim.exe,自动和服务器联网。在服务器下达通知消息时,会自动跳出提示,播放声音,几秒后停止。
    要求播放的声音需要从功放输出,保证范围内所有人能听见。一般来说功放需要24小时不间断开机,但长时间设备容易老化损坏。
    需要改造成在有提示声音播放时再自动打开功放电源,播放完毕自动断开功放电源。在程序源代码中增加这个功能也非常容易。
    但本文从另一个角度来探讨:如果不修改源代码,能否实现增加功能呢?


    【改造思路】
    1、逆向分析EXE文件,找出提示开始和结束的代码;
    2、编写自己的DLL文件,以供EXE调用实现功能;
    3、改造EXE文件(添加DLL导入函数、打补丁调用函数)。


    【知识准备】
    1、大致了解EXE文件的结构、加载到内存的方式等
    2、反汇编与调试
    3、DLL的代码编写
    4、EXE修改


    【使用工具】
    查壳工具:DiE
    调试工具:OD
    编程工具:vs2010(很老了……)
    修改工具:StudyPE+、010Editor
    记录工具:Programmer's Notepad
    抓包工具:Wireshark


    【过程记录】
    一、逆向分析EXE文件,找出提示开始和结束的代码
    1、上手用DiE查了一下,VC编译win32,无壳,studype查为动态基址。这一步并不是很难,如果是遇到加密加壳的,像我这种新手就无能为力了。
    2、直接拖入OD,停在OEP(012BFCCC) 如果没有在OEP点一下小人运行到用户代码就行。接着点一下Az搜索字符串,因为字符串包含大量提示信息,很可能找到我们要的东西
    TBC茶馆-复仇者黑客组织新手第一次写逆向和改造的过程,难免有错误或走弯路的地方,请大神们多多指正。本文旨在探讨程序编写技能复仇者黑客组织(1)
    3、果然,很快找到VoiceXXX::stop()和VoiceXXX::OnReceiveWarning()之类的信息,应该是写日志用的,字面一看这不就是声音的结束和开始吗,就从这里下手吧。
    双击点进去,把地址记录下来,准备打补丁。
    TBC茶馆-复仇者黑客组织新手第一次写逆向和改造的过程,难免有错误或走弯路的地方,请大神们多多指正。本文旨在探讨程序编写技能复仇者黑客组织(2)

    4、下面就是刚才那两处的地址
    可以看出,push了一个字符串,然后call某个函数。
    这种就很好打补丁,因为跳转的机器码和push字符串的机器码一样长(后面再说)。
    到这里,第一步分析完成。
    [Asm]  
    1. 012BAE83 | 68 9CEE2C01              | push victim.12CEE9C                                                    | 12CEE9C:"VoiceXXX::onReceivedWarning() type:"
    2. 012BAE88 | FF15 08A62C01            | call dword ptr ds:[<&public: class QDebug & __thiscall QDebug::operato |
    3. ......
    4. 012BA8A1 | 68 68EE2C01              | push victim.12CEE68                                                    | 12CEE68:"VoiceXXX::stop()"
    5. 012BA8A6 | FF15 08A62C01            | call dword ptr ds:[<&public: class QDebug & __thiscall QDebug::operato |
    复制代码


    二、编写自己的DLL文件,以供EXE调用实现功能
    这个可以用你自己喜欢的编写DLL的工具,写两个可以静态调用的函数,为了简单,没有参数,也没返回值。
    我用vs2010向导建立了WIN32dll项目,取名叫customsg,过程中最好要选一下“导出符号”以便导出函数
    我写了两个导出函数:MsgStart和MsgStop, 在函数里就可以做很多事情了,
    比如发送系统消息、给串口发数据、访问某个网址等都行。
    这里我采用了插入一个串口继电器,给串口发数据控制电源通断的方式。
    [C++]  
    1. //用于导出的函数
    2. // 开始消息,设置dwMsg = 1
    3. CUSTOMSG_API void MsgStart(void)
    4. {
    5.         wMsg = 1;
    6.         PostMessage(HWND_BROADCAST, nPostMsgID, wMsg, dwMsgVar);
    7.         SendSerialData(TRUE); //发送命令打开继电器
    8.         PostData(strPostUrl, strPostDataStart);
    9. }
    10. // 停止消息,设置dwMsg = 0
    11. CUSTOMSG_API void MsgStop(void)
    12. {
    13.         wMsg = 0;
    14.         PostMessage(HWND_BROADCAST, nPostMsgID, wMsg, dwMsgVar);
    15.         SendSerialData(FALSE);//发送命令关闭继电器
    16.         PostData(strPostUrl, strPostDataStop);
    17. }
    18. //其它函数及具体代码自己实现
    复制代码


    然后在项目中添加一个def文件用于导出规范名称的函数,要不然函数名是乱码的
    [Plain Text]  
    1. LIBRARY "customsg"
    2. EXPORTS
    3. MsgStart @1
    4. MsgStop @2
    复制代码


    编译成功,你就会得到一堆文件。我们只需要找到.dll这个:
    customsg.dll

    在Debug和Release目录都有,选一个复制到刚才那个victim.exe的目录中,这一步宣告完成。


    三、改造EXE文件(添加DLL导入函数、打补丁调用函数)
    这一步总体来说有点难度,我也是走了很多弯路才成功,遇到问题多百度可以解决掉大部分
    关键在于细致


    1、添加DLL导入函数
    用StudyPE+打开我的victim.exe,点击“导入”,出现导入dll列表,右键点击任意一个,点击“添加导入函数”
    TBC茶馆-复仇者黑客组织新手第一次写逆向和改造的过程,难免有错误或走弯路的地方,请大神们多多指正。本文旨在探讨程序编写技能复仇者黑客组织(3)

    浏览找到自己编写的custmsg.dll,从左侧选取要导入的函数(MsgStart、MsgStop),加到右侧,点击“添加”。
    TBC茶馆-复仇者黑客组织新手第一次写逆向和改造的过程,难免有错误或走弯路的地方,请大神们多多指正。本文旨在探讨程序编写技能复仇者黑客组织(4)

    完成后,点击“文件-另存为”,保存为"victim2.exe",DLL导入函数添加完毕。

    2、打补丁调用函数
    这里最好稍微有点汇编的知识,百度学习一下也行
    (1)再次启动OD,打开导入DLL函数的“victim2.exe",运行到用户代码,直接去我们在第一部分找到的地址处 按F2下个断点 方便找
    【这里有个问题,就是动态基址,每次程序加载后地址可能会不一样。如果图简单,可以在刚才StudyPE+里顺便点一下“固定基址”就OK,就不会变了】
    我这里就以动态基址的方式来改,也没问题,当作一次学习
    这里我们把刚才的地址,和刚才记的OEP地址(012BFCCC)减一下  再和现在的OEP地址(00F6FCCC)减一下,就能算出来了
    012BAE83 :    012BFCCC-012BAE83=4E49,  00F6FCCC-4E49=00F6AE83
    ......
    012BA8A1:    012BFCCC-012BA8A1=542B,  00F6FCCC-542B=00F6A8A1

    (2)在CPU窗口 按Ctrl+G输入要找的地址直接过去
    [Asm]  
    1. 00F6AE83 | 68 9CEEF700              | push victim2.F7EE9C                                                    | F7EE9C:"VoiceXXX::onReceivedWarning() type:"
    2. 00F6AE88 | FF15 08A6F700            | call dword ptr ds:[<&public: class QDebug & __thiscall QDebug::operato |
    3. ......
    4. 00F6A8A1 | 68 68EEF700              | push victim2.F7EE68                                                    | F7EE68:"VoiceXXX::stop()"
    5. 00F6A8A6 | FF15 08A6F700            | call dword ptr ds:[<&public: class QDebug & __thiscall QDebug::operato |
    复制代码


    (3)在代码前后附近找一些空闲空间,放补丁代码
    因为程序编译留了许多int3的调试指令,我们需要寻找一大片连续的CC字节 最好在20个以上
    按Ctrl+B搜索匹配特征,在十六进制处输入24个连续的CC,按“确定”
    TBC茶馆-复仇者黑客组织新手第一次写逆向和改造的过程,难免有错误或走弯路的地方,请大神们多多指正。本文旨在探讨程序编写技能复仇者黑客组织(5)

    运气好,搜索出来了在00F72EB2处有,双击点进去
    TBC茶馆-复仇者黑客组织新手第一次写逆向和改造的过程,难免有错误或走弯路的地方,请大神们多多指正。本文旨在探讨程序编写技能复仇者黑客组织(6)

    (4)果然一大片。我们留一两个CC再开始,我从00F72EB5开始写调用MsgStart的代码
    右键,二进制 编辑,
    前8字节改为
    60 FF 15 CC CC CC CC 61
    [Asm]  
    1. 00F72EB5 | 60                       | pushad                                                                 |
    2. 00F72EB6 | FF15 CCCCCCCC            | call dword ptr ds:[CCCCCCCC]                                           |
    3. 00F72EBC | 61                       | popad                                                                  |
    复制代码

    这段代码就可以完成调用某个函数的功能了,CCCCCCCC暂时不管,等会儿改成我们自己的函数地址

    接着把00F6AE83的5个字节写过来
    [Asm]  
    1. 00F72EBD | 68 9CEEF700              | push victim2.F7EE9C                                                    | F7EE9C:"VoiceXXX::onReceivedWarning() type:"
    复制代码

    最后加个跳转指令,跳回原来的call那里
    这里直接按空格键,输入"jmp 00F6AE88"就行
    TBC茶馆-复仇者黑客组织新手第一次写逆向和改造的过程,难免有错误或走弯路的地方,请大神们多多指正。本文旨在探讨程序编写技能复仇者黑客组织(7)
    然后双击jmp那条指令,跳到上面的call,将前面那条指令改成跳转到我们补丁地址 "jmp F72EB5"
    TBC茶馆-复仇者黑客组织新手第一次写逆向和改造的过程,难免有错误或走弯路的地方,请大神们多多指正。本文旨在探讨程序编写技能复仇者黑客组织(8)
    这样,就完成了EXE对我的DLL中MsgStart函数的调用框架
    梳理一下思路:
    在空闲区编写调用DLL函数的代码 -》在EXE中修改一条PUSH指令为JMP到空闲区 -》 空闲区调用DLL函数结束,执行原来的PUSH指令,JMP回去原来地址继续运行

    用同样的方法,完成MsgStop函数的调用框架编写
    TBC茶馆-复仇者黑客组织新手第一次写逆向和改造的过程,难免有错误或走弯路的地方,请大神们多多指正。本文旨在探讨程序编写技能复仇者黑客组织(9) TBC茶馆-复仇者黑客组织新手第一次写逆向和改造的过程,难免有错误或走弯路的地方,请大神们多多指正。本文旨在探讨程序编写技能复仇者黑客组织(10)

    (5)修复调用的DLL函数的地址
    首先,到OD中,点击“符号”,选中左侧第一个"victim2.exe",在右边会出现许多它的导入函数。由于我们添加的DLL在最后,因此我们拉到最下面,会找到导入的两个函数:
    TBC茶馆-复仇者黑客组织新手第一次写逆向和改造的过程,难免有错误或走弯路的地方,请大神们多多指正。本文旨在探讨程序编写技能复仇者黑客组织(11)

    记住这两个地址,并分别填写到刚才的CCCCCCCC处【注意低字节在前】
    02A04C30 =customsg.MsgStart
    02A04C34 =customsg.MsgStop
    同时记下左上角黑色显示的那个基址【 00F40000】,下面要用到
    TBC茶馆-复仇者黑客组织新手第一次写逆向和改造的过程,难免有错误或走弯路的地方,请大神们多多指正。本文旨在探讨程序编写技能复仇者黑客组织(12)
    可以看到,call的函数名称显示正确了
    可是不要高兴得太早,因为这是动态基址,下一次运行还会变

    (6)我们要计算出它的正常基址,让它再怎么变都能找到。
    方法:用函数地址减去上面的基址【00F40000】,再加上正常基址【EXE一般为400000】,用StudyPE+可以查看ImageBase值。
    02A04C30-00F40000+400000 =【01EC4C30】    //customsg.MsgStart
    02A04C34-00F40000+400000 =【01EC4C34】    //customsg.MsgStop
    同样的,上面我们PUSH的那个参数,也是动态地址,也需要减去上面的基址【00F40000】,再加上正常基址【EXE一般为400000】
    68 9CEEF700 -》68 【9CEE4300】
    68 68EEF700 -》68 【68EE4300】

    在OD中,把这4个值对应修改进去
    TBC茶馆-复仇者黑客组织新手第一次写逆向和改造的过程,难免有错误或走弯路的地方,请大神们多多指正。本文旨在探讨程序编写技能复仇者黑客组织(13)

    (7)记录数据偏移地址
    OD里修改好了,等会儿还要在EXE文件里去修改。在动态基址的情况下,这几个值程序在加载的时候会重新计算,因此要找出这几个值在EXE文件加载时的偏移地址。
    方法:数据地址减去基址【00F40000】
    TBC茶馆-复仇者黑客组织新手第一次写逆向和改造的过程,难免有错误或走弯路的地方,请大神们多多指正。本文旨在探讨程序编写技能复仇者黑客组织(14)
    将这几个地方都算出来
    [Asm]  
    1. 32EB6                 //00F72EB6 | FF15 304CEC01            | call dword ptr ds:[1EC4C30]                                            |
    2. 32EBD                //00F72EBD | 68 9CEE4300              | push 43EE9C                                                            |
    3. 32ECA                //00F72ECA | FF15 344CEC01            | call dword ptr ds:[1EC4C34]                                            |
    4. 32ED1                //00F72ED1 | 68 68EE4300              | push 43EE68                                                            |
    复制代码

    由于每个指令前面是操作码FF15或68,后面才是数据,因此要加1到2字节,算出数据的地址:
    [Plain Text]  
    1. 32EB8
    2. 32EBE
    3. 32ECC
    4. 32ED2
    复制代码

    留着备用。

    (8)应用补丁到文件
    在OD中点右键,点击“补丁”,在出现的对话框中点击“全选” -》 “修补文件”,另存为"victim3.exe"
    另存的时候可能会有个提示 “你的补丁和重定向区域重叠”,点YES就行
    TBC茶馆-复仇者黑客组织新手第一次写逆向和改造的过程,难免有错误或走弯路的地方,请大神们多多指正。本文旨在探讨程序编写技能复仇者黑客组织(15)

    (9)为我们的补丁增加重定向项目
    下载一个最新的010 Editor,打开victim3.exe,会提示你安装EXE模板,点“安装”。
    完成后打开的victim3.exe会变得五颜六色,下面也会多出来分析的目录树:
    TBC茶馆-复仇者黑客组织新手第一次写逆向和改造的过程,难免有错误或走弯路的地方,请大神们多多指正。本文旨在探讨程序编写技能复仇者黑客组织(16)

    在目录树里找到 RelocTable, 可以看到尺寸大小是78D0H
    TBC茶馆-复仇者黑客组织新手第一次写逆向和改造的过程,难免有错误或走弯路的地方,请大神们多多指正。本文旨在探讨程序编写技能复仇者黑客组织(17)

    向下滑动到下面,找到RelocTable的最后一项点一下。可以看到最后一项后面有许多0,这里可以增加我们自己的重定位项。
    TBC茶馆-复仇者黑客组织新手第一次写逆向和改造的过程,难免有错误或走弯路的地方,请大神们多多指正。本文旨在探讨程序编写技能复仇者黑客组织(18)

    重定位项的结构可以百度一下。
    第1个四字节:VirtualAddress,可以理解为EXE展开到内存中的地址。这个要进行4K对齐,也就是以十六进制1000H为整数倍。
      找到第(7)步记录的偏移地址,看到我们的数据都在32EB8到32ED2,因此第1个VirtualAddress填32000H 【00 20 03 00】
    第2个四字节:BlockSize,就是这个重定位块的长度。每个数据2字节 乘以四=8字节,再加上VirtualAddress和BlockSize,一共16字节,因此这里填10H 【10 00 00 00】

    接下来是具体的重定位项,就是相对VirtualAddress的偏移量 【数据地址减去VirtualAddress】
    根据重定位项定义,最高4个二进位值设置为“3”,表示这是个相对地址,加载时需要重新计算

    以第一个数据的重定位项为例:数据地址 - VirtualAddress = 32EB8 - 32000 = EB8
    最高4个二进制位设为3,合起来就是 3EB8H  【B8 3E】
    同理,可算出其它3个数据的重定位项:【BE 3E】【CC 3E】【D2 3E】
    紧挨着上面的数据,依次填充进去 :
    TBC茶馆-复仇者黑客组织新手第一次写逆向和改造的过程,难免有错误或走弯路的地方,请大神们多多指正。本文旨在探讨程序编写技能复仇者黑客组织(19)

    最后,修改一下重定位表大小,确保我们添加的才能有效
    方法:目录树上滑到开头,依次展开 NtHeader -》OptionalHeader -》DataDirArray,
    找到一个“BaseRelocationTable”展开,点一下“Size”,看到是【D0 78 00 00】,也就是刚刚我们看到的78D0H
    给它加上我们增加的块大小10H,得到78E0H ,所以将上面的数据修改为:【E0 78 00 00】,保存文件或另存为“victim4.exe"
    TBC茶馆-复仇者黑客组织新手第一次写逆向和改造的过程,难免有错误或走弯路的地方,请大神们多多指正。本文旨在探讨程序编写技能复仇者黑客组织(20)

    (10)大结局
    至此,EXE文件的改造工作全部结束。
    再次用StudyPE+打开我们改造过后的EXE,查看导入表和重定位表,确认都没有问题。
    TBC茶馆-复仇者黑客组织新手第一次写逆向和改造的过程,难免有错误或走弯路的地方,请大神们多多指正。本文旨在探讨程序编写技能复仇者黑客组织(21) TBC茶馆-复仇者黑客组织新手第一次写逆向和改造的过程,难免有错误或走弯路的地方,请大神们多多指正。本文旨在探讨程序编写技能复仇者黑客组织(22)

    运行测试,EXE程序工作正常,串口数据发送正常,电源控制正常。

    由于技术生疏,边学边改,以上程序前后经历了一周多才完成。
    因此记录下来,希望能给初接触EXE文件修改的新手们一点参考。




    上一篇:0基础入门通杀型 js hook
    下一篇:新版RaiDrive去广告-半完美

    该用户从未签到

    6

    主题

    2027

    帖子

    1677

    积分

    金牌会员

    Rank: 6Rank: 6

    积分
    1677
    发表于 2023-12-8 12:09:58 | 显示全部楼层
    1.studype去掉重定位跟动态基址 你可以省点事儿
    2.extern "C" 两个函数声明时加这个 ,可以避免C++函数乱码,据说是因为C+有重载
    3.然后其实可以直接inline hook 避免手动汇编
    回复

    使用道具 举报

    该用户从未签到

    1

    主题

    2086

    帖子

    1915

    积分

    金牌会员

    Rank: 6Rank: 6

    积分
    1915
    发表于 2023-12-8 12:10:50 | 显示全部楼层
    感谢楼主分享,不知道何时自己也能做到
    回复

    使用道具 举报

    该用户从未签到

    6

    主题

    2027

    帖子

    1677

    积分

    金牌会员

    Rank: 6Rank: 6

    积分
    1677
    发表于 2023-12-8 12:11:35 | 显示全部楼层
    感谢楼主分享
    回复

    使用道具 举报

    该用户从未签到

    8

    主题

    2004

    帖子

    1916

    积分

    金牌会员

    Rank: 6Rank: 6

    积分
    1916
    发表于 2023-12-8 12:12:01 | 显示全部楼层
    感谢大佬分享
    回复

    使用道具 举报

    该用户从未签到

    3

    主题

    1995

    帖子

    1181

    积分

    金牌会员

    Rank: 6Rank: 6

    积分
    1181
    发表于 2023-12-8 12:12:47 | 显示全部楼层
    感谢指点,又学到了新的思路

    我再去看一看inline hook方面的知识
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2024-1-18 14:31
  • 0

    主题

    7

    帖子

    51

    积分

    注册会员

    Rank: 2

    积分
    51
    发表于 2024-1-18 14:47:41 | 显示全部楼层
    非常有用,感谢分享
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    关闭Powered by ©科大讯飞语音云
    嗨!您好:
    欢迎来到 复仇者黑客组织。
    我的名字叫小光
    很高兴能够为您服务!
    如果已经注册【立即登录】
    还没有账号请立即注册
    Loading...
    快速回复 返回顶部 返回列表