关于对加壳后DLL的调试分析的笔记
2010-06-20 21:02
204 查看
这个是很久之前分析一个DLL时的文章了。写在了QQ空间里面。现在翻出来,慰问下自己。
其实不算是高明的东西。之前在分析一个样本时,该样本释放出了一个DLL,由于脱壳的功力不够强悍,但是便于分析。就自己写了个程序来调用。OnlyDBG虽然可以LoadDll插件来加载,但是个人感觉复杂(也许是没有用好的关系),我更喜欢此种方式,代码简陋,不要耻笑:)
有如下代码片段
#include <windows.h>
#include <stdio.h>
_declspec (dllexport) void FuncationName(ParamType Param,...);
int main(int argc ,char *argv[])
{
HMODULE hDll = NULL;
FARPROC FunAddr;
hDll = LoadLibrary("DllName.dll");
if(hDll==INVALID_HANDLE_VALUE)
{
printf("dll load fail/r/n");
return 0;
}
else
{
FunAddr = GetProcAddress(hDll,"FuncationName");
if(FunAddr==NULL) return 0;
__asm CALL FunAddr
}
FreeLibrary(hDll);
return 0;
}
我们知道DLL是不能够像exe那样运行的,是被动态加载的。所以在调试的时候很不方便,因为单单在IDA的静态反汇编工具里面,你没有办法看到寄存器的变化情况。既然DLL能被其他程序调用,那么就很好办了,自己实现一个测试程序加载之就可以了。但是这里涉及到一个问题,就是导出函数。DLL都有导出函数,但是加壳过后是否也有导出函数呢?回答是肯定的。如果你了解一些PE文件的知识,你就知道EXE这样的文件不需要重定位,但是DLL却不同,不同的机器,dll被加载到内存中的地址是不一样的,这也就是为什么DLL一般都有重定位节的原因。所以,作者不可能无聊到要通过使用直接地址的形式,我的意思是说假如有一个DLL被加载到内存中后,其中的一个Funcation地址为0x11111111(我这个只是假设),那么在他的程序中采取这样的形式:
__asm call 0x11111111
我想,这样多半要出问题。所以,要动计算函数的地址,但是又太麻烦。而将一个函数声明为导出函数却方便了很多,事实上也正是这样做的。所以我们只需要得到这个导出函数的地址,那么便可以跟进去看个究竟了。函数的名字很容易获取到,你可以使用VC的一个Depends去查看导出的函数名字。有了名字,就可以用上面的代码获取到该函数的地址了。我这的代码堆栈肯定没有平衡,但是我想,作为一个测试例子,应该还是足够了。
接下来就是将我们自己的程序加载到调试器当中,然后下好断点,就可以跟踪DLL中的函数了。非常方便。不过我这个只是一般的情况,其他的没有遇到过,只是一个思路而已。欢迎拍砖
其实不算是高明的东西。之前在分析一个样本时,该样本释放出了一个DLL,由于脱壳的功力不够强悍,但是便于分析。就自己写了个程序来调用。OnlyDBG虽然可以LoadDll插件来加载,但是个人感觉复杂(也许是没有用好的关系),我更喜欢此种方式,代码简陋,不要耻笑:)
有如下代码片段
#include <windows.h>
#include <stdio.h>
_declspec (dllexport) void FuncationName(ParamType Param,...);
int main(int argc ,char *argv[])
{
HMODULE hDll = NULL;
FARPROC FunAddr;
hDll = LoadLibrary("DllName.dll");
if(hDll==INVALID_HANDLE_VALUE)
{
printf("dll load fail/r/n");
return 0;
}
else
{
FunAddr = GetProcAddress(hDll,"FuncationName");
if(FunAddr==NULL) return 0;
__asm CALL FunAddr
}
FreeLibrary(hDll);
return 0;
}
我们知道DLL是不能够像exe那样运行的,是被动态加载的。所以在调试的时候很不方便,因为单单在IDA的静态反汇编工具里面,你没有办法看到寄存器的变化情况。既然DLL能被其他程序调用,那么就很好办了,自己实现一个测试程序加载之就可以了。但是这里涉及到一个问题,就是导出函数。DLL都有导出函数,但是加壳过后是否也有导出函数呢?回答是肯定的。如果你了解一些PE文件的知识,你就知道EXE这样的文件不需要重定位,但是DLL却不同,不同的机器,dll被加载到内存中的地址是不一样的,这也就是为什么DLL一般都有重定位节的原因。所以,作者不可能无聊到要通过使用直接地址的形式,我的意思是说假如有一个DLL被加载到内存中后,其中的一个Funcation地址为0x11111111(我这个只是假设),那么在他的程序中采取这样的形式:
__asm call 0x11111111
我想,这样多半要出问题。所以,要动计算函数的地址,但是又太麻烦。而将一个函数声明为导出函数却方便了很多,事实上也正是这样做的。所以我们只需要得到这个导出函数的地址,那么便可以跟进去看个究竟了。函数的名字很容易获取到,你可以使用VC的一个Depends去查看导出的函数名字。有了名字,就可以用上面的代码获取到该函数的地址了。我这的代码堆栈肯定没有平衡,但是我想,作为一个测试例子,应该还是足够了。
接下来就是将我们自己的程序加载到调试器当中,然后下好断点,就可以跟踪DLL中的函数了。非常方便。不过我这个只是一般的情况,其他的没有遇到过,只是一个思路而已。欢迎拍砖
相关文章推荐
- [转] 关于《Linux常用调试和性能分析工具》的学习笔记
- .NET / Rotor源码分析5 - 开始使用WinDbg+SOS调试,sscoree.dll,加载SOS并设置JIT断点
- 关于多线程 DLL (/MD)与多线程调试(/MTd)
- mesa3d源代码阅读笔记(4)_GLResize()函数调试执行分析
- 一个关于函数内部指针参数返回的错误调试及分析
- .NET / Rotor源码分析5 - 开始使用WinDbg+SOS调试,sscoree.dll,加载SOS并设置JIT断点
- 【MyBean调试笔记】关于单元的释放顺序
- [笔记].关于使用fscanf无法录入正确数据的原因分析
- HC-05蓝牙模块调试笔记以及使用正点原子例程无法检测到蓝牙模块原因分析
- [笔记].关于使用JLINK的三线SWD模式调试NUC1xx的一点粗浅认识
- 关于在VB.NET中调用使用VC++编写的类库dll的一点笔记
- 关于谷歌浏览器调试的笔记(一)
- SRS学习笔记9-rtmp监听线程创建推流线程的过程分析-gdb调试
- 孙鑫关于DLL(Dynamic Link Library)动态链接库的视频讲座笔记和学习小结
- .NET / Rotor源码分析5 - 开始使用WinDbg+SOS调试,sscoree.dll,加载SOS并设置JIT断点
- .NET / Rotor源码分析5 - 开始使用WinDbg+SOS调试,sscoree.dll,加载SOS并设置JIT断点
- Python 开发工具集:关于文档、测试、调试、程序的优化和分析
- .NET / Rotor源码分析5 - 开始使用WinDbg+SOS调试,sscoree.dll,加载SOS并设置JIT断点
- [关于OPC的研究1]c# opc client源码调试和学习笔记