通过Process Monitor的日志确认程序的行为(已附上下载地址)
sample_mal.exe下载地址
在运行sample_mal.exe前一秒,运行Process Monitor(防止Process Monitor日志过多,查找sample_mal.exe的行为会有困难)
双击运行sample_mal.exe(位置在binarybook-master\chap01\sample_mal\Release)
运行后有"Hello Malware"的对话框出现。
关掉对话框后,sample_mal.exe也会消失。
查看Process Monitor的日志,可以看到samlpe_mal.exe执行了CreatFile操作。
在C:\Users\33232\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup创建了一个0.exe
存放在"启动"文件夹的程序,会跟着windows的启动自动运行。
这个sample_mal.exe程序执行了CreatFile、WriteFile、CloseFile这几个操作,即等价于"在指定文件夹创建并写入一个0.exe"
使用010查看sample_mal.exe和0.exe,发现两个文件内容相同,即程序将自己复制了一份。(这里在下方找到了compare板块,但是不知道怎么用,也没搜到教程)
静态分析一波
使用010打开wsample01a.exe(注意这个文件在binarybook-master\chap01\wsample01a\Release,不是上一节的那个exe了)
这些16进制字符,就是Windows的可执行文件格式,即"PE格式"的文件内容。
可以从右侧的text中看出一些字符串"MESSAGE"、'‘Hello ! Windows’
文件路径"C:\Documents and Settings\XPMUser\My Documents\Visual Studio 2010\Projects\wsample01a\Release\wsample01a.pdb"
字符串"KERNEL32.dll"、“MessageBoxW”
可以使用Shift+F4打开Names windows窗口,也可以View—>Open subviews—>Names打开
双击Names windows窗口最上方的wWinMain函数,IDA View-A窗口中就会出现反汇编代码,默认为Graph view
IDA在这个视图中,会显示出调用的函数以及传递的参数。
可以看出,我们通过IDA发现的字符串是相当的多。
命令行里用参数2012跑一下
向wsample.exe里传递参数2012后,弹出"Hello! 2012"
再试试2013:
弹出了"Hello! Windows"
再试试无参数情况:
也弹出了"Hello! Windows"
F5查看伪代码,可以看出来有个比较2012与命令行参数的行为
(这里电脑蓝屏丢失了一段Process Monitor过滤规则查看wsample01b.exe,,不补写了,和sample_mal.exe类似)
下面使用调试器进一步跟踪程序逻辑,调试器可以发现程序问题和bug,可以设置断点;单步跳入、跳出;查看寄存器和内存数据
断点能够在任意位置中断和恢复运行
每执行一条指令都中断一次叫做单步跳入或跳出
跳入:调用函数时进入函数内部
跳出:调用函数时不进入函数内部,而是将函数调用作为一条指令来执行
使用OllyDbg打开wsample01b.exe
左上是反汇编窗口
左下是内存转储数据
右上是寄存器
右下是当前栈
现在反汇编窗口中显示出地址00401000后的程序逻辑
汇编代码如下:
可以看出,程序调用了GetModuleFileNameW、SHGetFolderPathW、lstrcatW、CopyFileW函数
已经使用Process Monitor发现程序会向"启动"文件夹复制文件,所以推测这个CopyFileW函数就是用来执行这个操作的。
我们可以通过单步运行功能来确认:
选中地址00401000所在的行,然后按F2,或者单击右键从菜单中选择Breakpoint—>Toggle
00401000的背景变成红色,说明已经成功地在该处设置了断点。
按F9,或者点击Debug—>Run
OllyDbg会启动wsample01b.exe,到达断点所在的00401000位置时,程序会暂停运行。
通过单步运行,逐条运行程序中的指令。
F7表示单步跳入,F8表示单步跳出
这里还不需要进入GetModuleFileNameW和SHGetFolderPathW函数的内部,所以按F8
每按一次F8,程序都会执行一条指令,同时右上方的寄存器窗口和右下方的栈窗口的内容都会发生变化
一直按F8,直到到达00401062的位置,即调用CopyFileW之前的位置
通过寄存器窗口和栈窗口,可以看到要复制的文件源路径和目标路径
此时,CopyFileW还没有被调用,所以"启动"文件夹中还没有文件
如果我们在这里继续按F8,程序就会调用CopyFileW函数,此时"启动"文件夹中,出现了wsample01b.exe
#include
#include
#include
int cpy(void)
{
// 获取自身文件路径
TCHAR szThis[2048];
GetModuleFileName(NULL, szThis, sizeof(szThis));
// 获取启动文件夹路径
TCHAR szStartup[2048];
SHGetFolderPath(NULL, CSIDL_STARTUP,
NULL, SHGFP_TYPE_CURRENT, szStartup);
lstrcat(szStartup, _T("\\wsample01b.exe"));
// 将自身复制到启动文件夹
CopyFile(szThis, szStartup, FALSE);
return 0;
}
int APIENTRY _tWinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
cpy();
MessageBox(GetActiveWindow(),
_T("Copied!"), _T("MESSAGE"), MB_OK);
return 0;
}
call指令是调用子程序用的,它的返回值放在eax中
传递给子程序的参数,通过push指令存放在栈中
每次执行push指令,push的值就会被放入栈中
比如:
在C语言中:
function(1,2,3);
汇编语言中的函数调用:
push 3
push 2
push 1
call function
//汇编语言中,参数按照从后往前的顺序入栈
//参数通过栈在传递