查找其签名在Windows DLL中的函数 [英] Find a function by it signature in Windows DLL

查看:178
本文介绍了查找其签名在Windows DLL中的函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

已经找到了一个DLL函数的地址。没有源$ C ​​$ C这个DLL,不是我的。此DLL是不是真的经常改变,但是改变的时候,这是一个问题,我通过拆解发现它。看到了有关使其签名,然后由该保存的签名发现它在网上的一些注意事项。 你能不能请,就如何实现这一一些想法或工作的例子吗?

Have found a function address in a DLL. Have no source code for this DLL, not mine. This DLL is not really changed frequently, but when changed, it is a problem for me to find it by disassembling. Saw some notes in web about making it signature and then find it by this saved signature. Can you, please, give some ideas or working example on how to implement this?

推荐答案

您可以用code特征码扫描,这是我在过去做了实现这一目标。的概念主要工作原理是依靠一个事实,即函数通常不改变更新之间的太多,而仅仅移居因为被向前或向后推压由其他功能正在扩大或缩小。

You can achieve this by code signature scanning, which is something I have done in the past. The concept mainly works by relying on the fact that functions often do not change too much between updates, but simply relocate because they were pushed forward or back by other functions being expanded or shrunk.

让我们来 MessageBoxA 的例子,谁的拆卸看起来像这样对我说:

Let's take the example of MessageBoxA, who's disassembly looks like this for me:

765DEA11 > 8BFF             MOV EDI,EDI
765DEA13   55               PUSH EBP
765DEA14   8BEC             MOV EBP,ESP
765DEA16   833D 749A5E76 00 CMP DWORD PTR DS:[765E9A74],0
765DEA1D   74 24            JE SHORT USER32.765DEA43
765DEA1F   64:A1 18000000   MOV EAX,DWORD PTR FS:[18]
765DEA25   6A 00            PUSH 0
765DEA27   FF70 24          PUSH DWORD PTR DS:[EAX+24]
765DEA2A   68 A49E5E76      PUSH USER32.765E9EA4
765DEA2F   FF15 34145876    CALL DWORD PTR DS:[<&KERNEL32.Interlocke>; kernel32.InterlockedCompareExchange
765DEA35   85C0             TEST EAX,EAX
765DEA37   75 0A            JNZ SHORT USER32.765DEA43
765DEA39   C705 A09E5E76 01>MOV DWORD PTR DS:[765E9EA0],1
765DEA43   6A 00            PUSH 0
765DEA45   FF75 14          PUSH DWORD PTR SS:[EBP+14]
765DEA48   FF75 10          PUSH DWORD PTR SS:[EBP+10]
765DEA4B   FF75 0C          PUSH DWORD PTR SS:[EBP+C]
765DEA4E   FF75 08          PUSH DWORD PTR SS:[EBP+8]
765DEA51   E8 73FFFFFF      CALL USER32.MessageBoxExA
765DEA56   5D               POP EBP
765DEA57   C2 1000          RETN 10

诀窍是在code的一些块,你认为可能会保持不变,在更新猜测,但更重要的是独一无二的这个功能。通常情况下,它是无用扫描尾声/序幕。我可能会采取以下块:

The trick is to guess at some block of code which you think is likely to stay the same in an update, but more importantly is unique to this function. Typically, it is useless to scan for the epilogue/prologue. I would probably take the following block:

765DEA16   833D 749A5E76 00 CMP DWORD PTR DS:[765E9A74],0
765DEA1D   74 24            JE SHORT USER32.765DEA43
765DEA1F   64:A1 18000000   MOV EAX,DWORD PTR FS:[18]
765DEA25   6A 00            PUSH 0
765DEA27   FF70 24          PUSH DWORD PTR DS:[EAX+24]
765DEA2A   68 A49E5E76      PUSH USER32.765E9EA4
765DEA2F   FF15 34145876    CALL DWORD PTR DS:[<&KERNEL32.Interlocke>; 

您有选择块的长度时,使平衡。的时间越长的块,越有可能是唯一地识别功能,也就越有可能的是,一些code将这意味着它是分裂等。注意,该块我选择在更新期间被插入有多个内存引用。我们不能依赖于任何数据或函数的地址,因为这些可能会在下次更新时被重新定位,所以我们填补这些字节使用通配符:

You have to make a balance when choosing the length of the block. The longer the block, the more likely it is to uniquely identify a function, but also the more likely it is that some code will be inserted during the update which means it is split, etc. Note that the block I have chosen has multiple memory references. We can not rely on any data or function addresses since these may be relocated on the next update, so we fill those bytes with wildcards:

765DEA16   833D XXXXXXXX 00 CMP DWORD PTR DS:[XXXXXXXX],0
765DEA1D   74 XX            JE SHORT XXXXXXXX
765DEA1F   64:A1 18000000   MOV EAX,DWORD PTR FS:[18]
765DEA25   6A 00            PUSH 0
765DEA27   FF70 24          PUSH DWORD PTR DS:[EAX+24]
765DEA2A   68 XXXXXXXX      PUSH XXXXXXXX
765DEA2F   FF15 XXXXXXXX    CALL DWORD PTR DS:[XXXXXXXX] 

这意味着我们的字节的签名现在是:

This means our byte signature is now:

0X83 0X的0x3D? 0X? 0X? 0X? 0x74 0X? 0x64 0xA1为0x18为0x00为0x00为0x00的0x6A
  为0x00 0xFF的0x70 0X24为0x68 0X? 0X? 0X? 0X?为0xFF为0x15 0X? 0X? 0X? 0X?

0x83 0x3D 0x? 0x? 0x? 0x? 0x74 0x? 0x64 0xA1 0x18 0x00 0x00 0x00 0x6A 0x00 0xFF 0x70 0x24 0x68 0x? 0x? 0x? 0x? 0xFF 0x15 0x? 0x? 0x? 0x?

0X?字节表示通配符这是我们希望改变字节。其他的人都是我们预计更新将不会改变字节。使用字节在运行时定位功能,则需要扫描这些字节(考虑通配符)。这个过程是大约这样:

The 0x? bytes indicate wildcards which are bytes we expect to change. The other ones are bytes we expect will not change in the update. To use the bytes to locate the function at runtime, you need to scan for these bytes (taking into account the wildcards). The process is approximately so:


  • 枚举过程中的所有可执行网页( VirtualQueryEx

  • 扫描发现字节签名(考虑到通配符 - 这是微不足道的实施为循环,从而跳过通配符字节)

  • 要获得真正的函数地址,修复了您从原来的功能块的偏移获得(在这种情况下,地址, 0x765DEA16 - 0x765DEA11 =&GT; 0x5的

  • Enumerate all executable pages of the process (VirtualQueryEx)
  • Scan for the byte signature we found (taking into account the wildcards - this is trivial to implement as a for loop which skips wildcard bytes)
  • To obtain the true function address, fix up the address you get with the offset of the block from the original function (in this case, 0x765DEA16 - 0x765DEA11 => 0x5)

实际上,而不是列举所有可执行页面,它往往是足够找到功能在这种情况下,位于内( user32.dll中)什么模块,并在该搜索只有模块。

Actually, rather than enumerating all executable pages, it is often enough to find what module the function lies within (user32.dll) in this case, and search within that module only.

这篇关于查找其签名在Windows DLL中的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆