最近在分析一个样本,然后样本核心payload里遇到了很多线程,关键的恶意代码也包含在这些线程里,之前调试多线程的时候笔者不是很熟悉,所以也是一点点实验,这次就总结下。
互联网一搜索,发现大多写的不明确。个人理解力有限,最初开始调试也没弄成功。
Ollydbg如何调试多线程
https://bbs.pediy.com/thread-213379.htm
ollydbg只能单线程调试,也就是每次只能跟一个线程。那么如何进行多线程调试呢?
方法:首先是设置StrongOD,如下图:
去掉这个勾
来到CreateThread函数处
第三个参数ThreadFunction指定了新线程的入口地址,第四个参数pThreadPram为新线程所需的参数。在入口地址处下断点,然后按F8过CreateThread后,发现无法跳转到断点处,此时需要手动修改它下面接着的代码,一般修改为Sleep函数,如果Sleep函数无效的时候,可以尝试WaitForSingleObject函数。
执行到Sleep后,会跳转到新线程入口点地址。以上是第一种方法来调试线程,还有另一种方法对其他线程进行调试。
在ollydbg显示当前线程列表里,选中主函数的线程,将其设置为最低优先级。之后在需要调试的线程指令中下一个断点,之后运行的时候才能断在线程内部。
附测试demo
#include <iostream> #include <windows.h> using namespace std; int g_i = 0; //线程W LRESULT myWorkThread(DWORD) { while (1) { g_i = g_i + 1; //这里改写变量 ::Sleep(2000); printf("myWorkThread:%d\n", g_i); } } //线程R int main(int argc, char* argv[]) { CloseHandle(::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)myWorkThread, NULL, 0, NULL)); while (1) { cout << "MainThread:" << g_i << endl; //手动在这里断下,然后下硬件写断点,OD无法在 myWorkThread 中断下 Sleep(6 * 1000); } system("pause"); return 0; }
有时候上面列举的方法不一定有效,所以下面记录一些查找到的操作步骤,已通过实践。首先下面就拿一个样本 https://bbs.pediy.com/thread-252833.htm 进行举例,该样本是最近分析的。如图,目前是已经来到了病毒核心payload部分。接下来直接步过来到创建线程的函数处。
0040A790内部就会开始创建线程,先步进看看。
如图所示,004068B0为CreateThread,所以新线程的函数的开始地址为0040A530。
跳转到反汇编窗口,或者直接使用快捷键Ctrl + G 输入需要跳转的地址,然后按下F2设置断点。
接着来到线程显示窗口,工具栏的t字母。
已经标识出主线程,现在我们要调试0040A530这个线程怎么办呢?来到主线程,也是就是发现CreateThread函数的位置。
此时再次来到线程窗口查看下
目前还没有改变,依然是之前已经存在的线程。现在在刚刚的主线程处下一个断点,放置到CreateThread函数之后,任意位置都行。
来到线程窗口,双击进入标识为A44线程。
进入了系统空间,F8单步步过运行下,发现直接就跳转到了刚刚我们想调试的新线程的起始地址。如图所示:
那么目前已经进入了新线程,如何再次回到主线程呢?由于是做演示,该线程我们先实际运行小部分指令后,然后再回到主线程。再次来到线程窗口,会发现已经出现了新的线程入口为0040A530。
双击主线程,进入看看,能不能回到主线程里。
发现进入了主线程里,而且由于之前设置过断点,程序已经暂停下来了,就又可以对主线程进行调试了。记录一下,这里的关键是要随时设置好断点,这样切换进程调试的时候,才能让程序暂停下来,否则一旦切换到新的线程,会一直运行下去,根本停不下来,~~~。接着看一个情况,当新线程退出时,如何返回到主线程里?还是拿上面运行的样本举例,如图是创建了0040A530线程后,接着还会创建一个0040A710线程,还是按照刚刚描述的步骤进入到0040A710线程里。
目前的线程窗口如下
查看线程窗口,发现还没有出现新线程。
双击其中的系统空间入口,进入看看。
直接断了下来,接着F8运行,会直接跳转到0040A710新线程起始地址。
和之前描述的步骤一样,在主线程创建线程往下执行的任意位置设置一个断点。
在0040A710新线程中F8步过运行,来到退出线程的地方。
进入看看
retn退出后,来到如下图的地方。
继续执行,看看。
处于运行状态,那这会如何回到主线程呢?首先还是来到线程窗口,
目前除了刚刚进入的0040A710线程,其余线程已经变成了暂停状态。
如图:
回到刚刚的0040A710线程退出后的系统空间指令里
先暂停程序, 快捷键F12。
暂停后,自动切换到了主线程里。
当按F8运行时。又没有断下来,处于运行状态。
在下图里还是按F12 让其暂停,按Alt + F9返回用户模式。
接着查看线程窗口,发现优先权变成了128+XXXX,此时,右键选择Resume All Threads。
现在又可以在主线程里调试了
之前在本地测试没有成功,在文章中就不敢提及了,后来在楼下@Adventure师傅的评论中,想着还是实践成功了再对文章进行补充吧,最后测试成功了。
第三种调试的方式是在调试选项里选择进入到新线程时或者离开时中断,如下图:
之后运行样本到函数内部里的第二个创建线程处,由于已经执行完毕第一个创建的线程函数,所以0040A530已经创建成功,但此时还没有跳转到0040A530。接下来按F8运行会自动跳转到0040A530新线程处,如下图:
查线程窗口发现存在0040A530新线程,双击下,进入内部看看。
发现确实中断在了新线程处
那么如何进入第二个创建的0040A710新线程处呢?查看下此时的线程窗口,如下图:
双击第二个线程,来到系统空间,之后运行会跳转到0040A710新线程处。如下图:
接着看,如何进入主线程呢?此时的线程窗口如下:
双击下主线程,同样也能进入到主线程中进行调试。
再看一下此时的线程窗口,发现这会创建的新线程都已经显示出来,之后对其余线程进行调试时同理。
文中如有错误,感谢指正。
https://blog.csdn.net/jishuzhain/article/details/95229532
https://stackoverflow.com/questions/9644875/how-to-use-ollydbg-with-multi-threaded-programs
https://ardsec.blogspot.com/2011/09/debugging-threads-olly.html
http://books.0x10dx.com/%E6%9C%AA%E5%88%86%E7%B1%BB/OllyDbg%20%E4%B8%AD%E6%96%87%E5%B8%AE%E5%8A%A9%E6%89%8B%E5%86%8C%202.0.1.pdf
[公告]看雪.纽盾 KCTF 2019晋级赛Q3攻击方规则,9月10日开赛,华为P30 Pro、iPad、kindle等你来拿!
最后于 2019-8-30 00:05 被jishuzhain编辑 ,原因: 补充