DLL 反汇编 【其他类文 请到幻影查看】

反汇编DLL文件 HOOKAPI 作者 彬

 

 

前段时间在CSDN上有位网友问过一个问题。如何在WINDOWS下使删除文件、复制文件、变更文件名失效呢?
  有一个办法,就是通过拦截系统的I/O中断,可以实现此操作。但是因为网友只是问如何在WINDOWS下失效,那我们也可以试着拦截API函数。众所周知,在WINDOWS下的文件操作一般是通过调用WINAPI函数实现的,再由WINAPI函数调用系统的I/O中断实现最终的文件操作。如果我们在系统调用WINAPI函数时将其拦下,那么文件操作不就失效啦吗?
  现在摆在我们面前的一个问题是,我们用何种方法来实现HOOKAPI函数,总的来分一共有两种:软模式和硬模式(呵呵,我起的名)。那什么叫软模式呢?软模式就是通过编写程序,使程序自动获得我们要截获得API函数的RVA(相对虚拟地址),然后在地址处写入我们的代码,使程序调用此API函数时先执行我们的代码,再返回执行原代码,别看我说得简单,但实际操作起来很麻烦,如程序在更改原API代码时必须进入RING0特权级等等问题都会摆在你的面前;硬模式是指利用手头上的软件直接更改相关DLL文件。由于软模式麻烦而且在2000下获得RING0特权级更麻烦,因此我们在此先讲如何利用硬模式达到我们预期的效果。
  系统常用的API函数基本都存在于Gdi32.dll、Kernel32.dll和Shell32.dll三个文件中,通过文件名我们就可以知道每个DLL文件中的API函数主要用在哪方面。
  这里我们要拦截的API函数是 SHFileOperation,是Shell32.dll中的函数此函数的用途删除文件、复制文件、移动文件、对文件更名。他有一个参数,是指向SHFILEOPSTRUCT结构的指针,其在ASM中的定义如下:
  SHFILEOPSTRUCT STRUCT
    hwnd          DWORD ?     ;调用者的窗口句柄
    wFunc         DWORD ?     ;指定是何种操作。(复制、删除等)
    pFrom         DWORD ?      ;来源目录或文件
    pTo          DWORD ?     ;目的目录或文件
    fFlags         FILEOP_FLAGS ? ;操作文件的旗标
    fAnyOperationsAborted DWORD ?     ;是否允许使用者中断
    hNameMappings     DWORD ?     ;不常用
    lpszProgressTitle   DWORD ?     ;不常用
  SHFILEOPSTRUCT ENDS

  关于此结构的详细资料,可以通过查阅MSDN来获得。

  好啦,函数名也知道啦,出自哪个文件也知道啦。下一步如何做呢?
  我们只要找到此函数在Shell32.dll中的位置,在其头部插入ret 4这条语句就可以啦。为什么要插入这条语句呢?我们不要系统对删除文件、复制文件等做出任何响应,只能让此API函数一调用时就马上返回就可以啦,因为此函数有一个参数,为了使堆栈恢复原状,因此堆栈指针需要加4。
  万事俱备,只欠不知道此函数在DLL文件中的地址啦。
  要知道其位置,我们可以自己编写个程序,算出来,不过现在我手头上已经有一个现成的啦,为什么还要再编一个呢?????打开getModule程序,此程序可以获得某个函数在某个DLL中的RVA地址。在软件的请输入DLL名框中键入“Shell32.dll“,在请输入函数名框中键入“SHFileOperation“,按下获取,得到地址:7fcedcf1h(可能由于98版本的不同,这里的数值会不一样。注意:此软件区分大小写。)。我们要对Shell32.dll文件反汇编所用的软件是HIEW,此软件中显示的地址是指文件内部的偏移地址,因此我们还需要将RVA地址转换成文件内部偏移地址。打开第二个软件RVA Converter点击菜单“FILE“中的“LOAD“选项“,选中我们要加载的文件“Shell32.dll“,然后再下面的RVA框中键入刚才得到的RVA地址,键入完毕后,FILE框中所显示的地址:3DCF1即“SHFileOperation“函数在“Shell32.dll“文件内的偏移地址。
  最关键的一步开始啦,打开HIEW软件,加载“Shell32.dll“,按下F4键,选择“DECODE“(反汇编),再按下F5键,键入刚才所得到的地址3DCF1,来到了我们要更改的函数的开头处,按下F3键进行编辑,再按下“TAB“键,可以直接键入汇编代码ret 4,之后按下F9键保存,退出程序。
  重新启动机器,来到DOS下,将改好的Shell32.dll替换掉原先的文件。再重启机器进入WINDOWS,试试删除文件,怎么样?删除不了吧!
  可能有人会问,我只想屏删除文件,我是不是只要按此方法拦DeleteFileA函数就可以啦?答案是不行的,开始我试验时拦的就是此函数,很怪的是如果你按下的是SHIFT+DEL进行删除文件,文件消失啦,但按一下F5刷新,文件就回来啦,达到要求,但是如果你通过回收站删除文件,那就不好用啦。因此最后我选择拦截SHFileOperation函数,如果你真得只想拦删除文件,可以通过编写程序检测SHFILEOPSTRUCT结构中的wFunc参数,来进行相应的操作达到你所想要的效果。这里有点唠叨啦。

  总是让系统不删文件,我想硬盘空间会慢慢变小,呵呵,有点像病毒啦!
  这种状态下我试了一个小时啦,不过没事,大家自己试试吧,出了问题可别找我啊!:)
  最后我们总结一下,这种硬模式法有好处有坏处,好处是操作简单,稍懂一些汇编的人都会理解整个操作步骤的,坏处是,如果98版本不一样的话,手工改动太麻烦啦,而且由于我们只是拦下了API函数,在98内好用,但是打开98的DOS窗口仍可以进行删除操作,这一点请大家注意。这里只是教大家一种方法,具体用到哪方面,就看你自己了。

 

dll反汇编初步

 

 


2004-5-15 2:17:52 (文章类别:编程基础)

ozymandias(原作)

在论坛里面看到一些人讨论dll的反汇编,这几天帮一个朋友分析一个dll,此dll非常简单,现在把我的分析过

程和大家分享一下,这里没有什么特别有效的方法,靠的就是耐心和经验,反复验证,直到调用成功。

有个dll2lib的工具,不知道是我不会使用还是怎么的,反正我是没有使用成功过,所以我只能靠自己

来分析了。

首先是使用的工具,ida/win32dasm/ollydbg

win32dasm分析的速度快一些,但是智能程度不如ida,ida这个2001开发工具亚军绝对不是浪得虚名的

,它的智能程度非常高,可是识别出常用的函数,这两个都是静态反汇编的工具,必须配以动态分析的工具,

毕竟你很难一下子就分析对(至少我是这样),当然你可以使用s-ice或者trw,但是这些工具都有限制,trw不支

持2000,s-ice一旦装载只能reboot才能取消装载,还有其工作在ring0,所以你只能对者黑乎乎的屏幕,很痛

苦,这里选用的ollydbg是最新版本,支持dll的跟踪。

下面列出win32dasm反汇编的结果:

Exported fn(): GetUserNumber - Ord:0004h
:0040C1B0 55push ebp
:0040C1B1 8BECmov ebp, esp
:0040C1B3 53push ebx
:0040C1B4 56push esi
:0040C1B5 57push edi
:0040C1B6 8B5D08mov ebx, dword ptr [ebp+08]
:0040C1B9 33F6xor esi, esi
:0040C1BB 8BC3mov eax, ebx
:0040C1BD E846A5FFFFcall 00406708
:0040C1C2 6685C0test ax, ax
:0040C1C5 7212jb 0040C1D9
:0040C1C7 40inc eax
:0040C1C8 33D2xor edx, edx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040C1D7(C)
|
:0040C1CA 0FB7CAmovzx ecx, dx
:0040C1CD 0FB60C0Bmovzx ecx, byte ptr [ebx+ecx]
:0040C1D1 03F1add esi, ecx
:0040C1D3 42inc edx
:0040C1D4 66FFC8dec ax
:0040C1D7 75F1jne 0040C1CA

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040C1C5(C)
|
:0040C1D9 8B450Cmov eax, dword ptr [ebp+0C]
:0040C1DC 8A4012mov al, byte ptr [eax+12]
:0040C1DF 3C61cmp al, 61
:0040C1E1 720Bjb 0040C1EE
:0040C1E3 25FF000000and eax, 000000FF
:0040C1E8 6683E861sub ax, 0061
:0040C1EC EB09jmp 0040C1F7

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040C1E1(C)
|
:0040C1EE 25FF000000and eax, 000000FF
:0040C1F3 6683E841sub ax, 0041

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040C1EC(U)
|
:0040C1F7 8B550Cmov edx, dword ptr [ebp+0C]
:0040C1FA 8A5213mov dl, byte ptr [edx+13]
:0040C1FD 80FA61cmp dl, 61
:0040C200 720Cjb 0040C20E
:0040C202 81E2FF000000and edx, 000000FF
:0040C208 6683EA61sub dx, 0061
:0040C20C EB0Ajmp 0040C218

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040C200(C)
|
:0040C20E 81E2FF000000and edx, 000000FF
:0040C214 6683EA41sub dx, 0041

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040C20C(U)
|
:0040C218 0FB7C0movzx eax, ax
:0040C21B 6BF81Aimul edi, eax, 0000001A
:0040C21E 0FB7C2movzx eax, dx
:0040C221 03F8add edi, eax
:0040C223 81F74D010000xor edi, 0000014D
:0040C229 83F701xor edi, 00000001
:0040C22C 8BC3mov eax, ebx
:0040C22E E8D5A4FFFFcall 00406708
:0040C233 2BF8sub edi, eax
:0040C235 8BC6mov eax, esi
:0040C237 B91A000000mov ecx, 0000001A
:0040C23C 99cdq
:0040C23D F7F9idiv ecx
:0040C23F 2BFAsub edi, edx
:0040C241 8BC7mov eax, edi
:0040C243 5Fpop edi
:0040C244 5Epop esi
:0040C245 5Bpop ebx
:0040C246 5Dpop ebp
:0040C247 C20800ret 0008

通过ret 008我们可以知道这个函数需要两个参数,通过mov eax, esi,我们可以知道这个函数有反回

值(这是因为在高级语言里面一般通过eax设置函数返回值)具体返回什么类型现在还没办法知道,但是不管这么

多,我们假设此函数是这样的:

int GetUserNumber(int a1,int a2)

我们会在后续分析后,慢慢修正他,现在我们开始一点点分析。

:0040C1B0 55push ebp
:0040C1B1 8BECmov ebp, esp
:0040C1B3 53push ebx
:0040C1B4 56push esi
:0040C1B5 57push edi
这个是function prolog,建立堆栈和寄存器的保存,没什么可多说的。
:0040C1B6 8B5D08mov ebx, dword ptr [ebp+08]
:0040C1B9 33F6xor esi, esi
:0040C1BB 8BC3mov eax, ebx
:0040C1BD E846A5FFFFcall 00406708

这里你需要知道函数调用过程的参数传递,可以到asm.yeah.net看看罗云彬那篇很好的关于参数传递和堆栈修

复的文章,这里简单说一下,调用函数的时候如果通过堆栈来传递参数的话,那么对于我们讨论的函数可能是

这样的:

push a2
push a1
call GetUserNumber

此时堆栈看起来是这样的

-----a2
-----a1
esp-> -----returnaddress
这时候进入函数内部push ebp后
esp+c -----a2
esp+8 -----a1
esp+4 -----returnaddress
esp-> -----ebp

mov ebp,esp

此时要寻址a1可以通过ebp+8

:0040C1B6 8B5D08mov ebx, dword ptr [ebp+08]; ebx保存第一个参数
:0040C1B9 33F6xor esi, esi
:0040C1BB 8BC3mov eax, ebx
:0040C1BD E846A5FFFFcall 00406708

这个很简单esi清零,把第一个参数传递给eax,然后调用00406708

所以我们接下来就是要到00406708里面去看看
:00406708 89FAmov edx, edi
:0040670A 89C7mov edi, eax
:0040670C B9FFFFFFFFmov ecx, FFFFFFFF
:00406711 30C0xor al, al
:00406713 F2repnz
:00406714 AEscasb
:00406715 B8FEFFFFFFmov eax, FFFFFFFE
:0040671A 29C8sub eax, ecx
:0040671C 89D7mov edi, edx
:0040671E C3ret

这个是很典型的求字符串长度的代码
:00406708 89FAmov edx, edi;保存edi
:0040670A 89C7mov edi, eax ;eax是我们调用前的a1
:0040670C B9FFFFFFFFmov ecx, F

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一、简介   AheadLib 是用来生成一个特洛伊DLL的工具,用于分析DLL中的函数参数调用(比如记录Socket send了什么等等)、更改函数功能(随心所欲了:)、更改界面功能(比如在Hook里面生成一个按钮,截获事件等等)。 二、使用   1.用 AheadLib 打开要模拟的 DLL,生成一个 CPP 文件。   2.用 Visual Studio 6.0/.NET 建立一个 DLL 工程,把这个 CPP 文件加入到项目中。   3.使用 Release 方式编译,生成的 DLL 将和原来的 DLL 具有一模一样的导出函数,并且能顺利把这些函数转发到原来的函数中。   4.AheadLib 还可以生成 Hook 代码,用于截取当前进程的所有消息,这样就可以随心所欲地处理各种消息了 (修改第三方程序界面功能的好助手)。 三、备注   1.如果导出函数过多,在 Visual Studio 6.0 中,如果出现编译错误,请在项目属性关闭与编译头功能。   2.如果是 C++ 、C __stdcall、C __fastcall 的方式导出的话,生成的函数声明将会还原成原代码级别(可能需要修改才能编译,比如导出C++类的情况)。此时使用 __declspec(dllexport) 导出 ——不能指定导出序号。   3.如果是 NONAME 或者 C _CDECL 方式导出(比如 DEF 导出,大多数Windows DLL都是这种情况,比如WS2_32等等),则使用#pragma comment(linker, "/EXPORT:...)导出,且指定导出序号。   4.如果系统中没有 DbgHelp.dll,将无法识别 C++ 模式的导出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值