恶意代码分析实战 ollydbg使用来了 Lab 9-1 9-2 9-3

Lab9-1:使用IDA Pro和OllyDbg分析恶意文件Lab9-1.exe,回答以下问题。

  1. 如何让这个恶意代码安装自身?
  2. 这个恶意代码的命令行选项是什么?它要求的密码是什么?
  3. 如何利用OllyDbg永久修补这个恶意代码,使其不需要指定的命令行密码?
  4. 这个恶意代码基于系统的特征是什么?
  5. 这个恶意代码通过网络命令执行了哪些不同操作?
  6. 这个恶意代码是否有网络特征?


       

 首先进行查壳,使用peid查询后发现无壳。之后静态分析应该进行查看字符串和导入表,但是这个程序有点大,也都会一步步分析到字符串和导入表,所以这两步跟动静分析一起结合。

 

首先,strings看到的结果:

 

然后,实际运行下,没有任何反应,倒是把自己给删除了,懵逼状态?就只有一个dll了。==》实际分析是因为他自己会有条件运行,不满足条件就会删除自己。当然,真正运行的时候,严谨的做法还是要promon或者procexp看看,因为真正的恶意软件也可能成功运行删除自己。

 

 

 

接下来,再在IDA里看下其调用关系图:

 

尤其是里面 有一个shellexecute,加上有网络请求connect、recv这些,所以基本上判断这个程序是一个远控shell后门,还会创建服务。

好了有了大致印象后继续往下看细节,看看为啥会自删除。

 

 

IDA打开实验文件,在主函数开始首先看到命令行参数检查:

        在402afd处看到对argc的比较,若参数个数为1则进入左侧执行,否则进入右侧。应注意的是在没有手动增加命令行参数时参数个数为1,就是如下效果:

         所以若加参数情况时,会进入左侧执行:调用sub_401000函数:

         进入sub_401000函数查看:

         可以看到在0040101B处调用RegOpenKeyExA打开注册表,若失败则将eax清零;成功的话利用RegQueryValueExA将目标注册表下的Configuration项添加键值,再把eax赋予1。静态分析至此有几个点需要结合动态分析验证:参数判断和打开注册表能够成功。OD中在00402AFD处下断点,F7单步发现会执行00402B03处的调用sub_401000函数操作,因为此时我们未加参数。

         OD中在00402B03处下断点之后直接F8步过:

         观察eax中的值,结合上述的静态分析可知,当eax为0时表示调用RegOpenKeyExA打开注册表失败。再回到静态分析:

         在00402B0A处的比较会进入左侧,调用sub_402410函数。进入sub_402410查看:

         使用GetModuleFileNameA函数获取文件路径,然后使用ShellExecuteA对文件进行操作。此时静态分析也可以看到一些字符串信息,我们再结合OD进行动态分析,在上面的3个API函数调用处设断点:

         在调用ShellExecuteA时可以看到参数"/c del C:\DOCUME~1\jilei\桌面\Lab09-01.exe >> NUL",所以可知 sub_402410函数既是删除自身功能。所以为了继续分析,我们应该增加参数使得执行路径发生变化,使用Strings分析Lab09-01.exe查看字符串,有没有能提供参考的参数可能:

         -in、-cc、-re更像是参数。在OD中添加参数:

         重启程序后在00402AFD处断点观察,eip指向402b1d。说明此时参数个数不是1。

         再回到IDA中分析,402b1d处将命令行参数个数赋给eax,将参数数组赋给ecx。402b23处为指针操作,获取到命令行参数数组中的最后一个元素。

 

         402b2e处调用sub_402510函数,进入该函数分析发现,并没用调用任何函数,大多是一些比较指令,推测是利用算法对参数进行检查。但是在尾部可以发现该函数比较成功则返回1(mov eax,1),失败则返回0(xor eax,eax)。若返回值为0则会调用sub_402410函数,这个函数前面分析过,删除自身;返回值为1进入右侧执行。OD中动态观察sub_402510函数返回值:

         此时eax为0,则说明接下来会执行删除自身操作。同样为了继续分析,patched二进制文件,使得sub_402510函数返回值为1。操作如下:重启程序,单步进入402b2e处的call,双击反汇编处输入mov eax,1回车之后再输入ret,

我的操作是a键再输入。。。。

 

 

 

 

 

         修改之后右键选择所有修改、点击全部复制。

         然后右键保存文件

        将Lab09-01_patched.exe使用OD打开,不要忘了加参数-in。在00402B38处下断点发现EIP指向00402B3F处。

         再回到IDA中静态分析00402B3F处,00402B3F和00402B42两处是对命令行参数数组的第二个元素的获取为Str1,有两处push字符串操作,随后调用__mbscmp函数进行字符串比较。分析可知应是对参数的比较。若比较成功则进入左侧00402B63处执行。

         OD中动态观察比较结果,此时栈中有两个-in,可以推测是对参数的比较。在00402B61处下断点,观察到程序到00402B63处执行。

         再回到IDA中分析00402B63处,00402B63处判断参数个数是否为3,是则进入左侧,否则进入右侧;00402B9A处判断参数个数是否为4,是则进入右侧,否则进入左侧。结合00402BBD处来看,若参数个数不为3也不为4则进入00402BBD处执行删除自身操作。此时我们的参数只有Lab09-01_patched.exe -in 两个,所以最终会执行到00402BBD处删除自身操作。

         再增加一个参数:

         OD中在00402B67处设置断点,程序到00402B69处执行。

         回到IDA中分析00402B69处。

         看到有一个sub_4025B0函数的调用,跟进:

         尾部可以得知返回值非1既0,在OD观察00402B75处函数返回值,在00402B7F处下断点观察EIP。

         此时EIP指向00402B89处,回到IDA中静态分析00402B89处。

         看到一个调用函数,跟进sub_402600函数分析

         首先看到对sub_4025B0函数的调用,该函数之前分析过,获取文件路径。

         使用OpenSCManagerA函数建立服务控制管理器,接下来利用OpenServiceA打开服务,若服务存在进入左侧调用ChangeServiceConfigA更改服务的配置参数;若服务不存在,调用CreateServiceA函数,此时注意004027EA处参数dwStartType为2,表示该服务为自启动。

         在执行关闭句柄操作后,调用ExpandEnvironmentStringsA 扩展环境变量字符串并将它们替换为为当前用户定义的值。

         调用CopyFileA将现有文件复制到新文件。

         跟进sub_401070函数分析,使用RegSetValueExA函数创建注册表项。

        使用RegSetValueExA函数将edx中的内容填充注册表下Configuration的键值。然后执行完毕。

 

         OD中验证我们的分析,在00402B90处下断点单步步进sub_402600函数。注意 00402805处的CreateServiceA函数,创建的服务名参数ServiceName="Lab09-01_patched.exe"。

       在004028A1处调用CopyFileA函数设置断点,此时根据参数可以看出将Lab09-01_patched.exe复制到C:\WINDOWS\system32\Lab09-01_patched.exe。

       在004028E0处调用sub_401070函数设置断点,单步跟进。在004011A8处调用RegCreateKeyExA函数设置断点,观察到创建的注册表为"SOFTWARE\\Microsoft \\XPS"。在004011D5处调用RegSetValueExA函数设置断点:

        注意参数Buffer,可以看出该值0012c314是一个内存地址,在内存窗口查看该地址 

        内容就是ups.http://www.practicalmalwareanalysis.com.80.60。

        再回到IDA中分析。

         -in aaaa参数的分析至此执行结束,可以分析出在该参数情况下,程序会创建一个与程序名同名的自启动的服务,并且在添加注册表。

        回到IDA中00402B61处继续分析,若此处的字符串比较失败则会进入00402BC7继续对参数进行比较,逻辑关系与00402B3F相同。结合Strings分析出的字符串可以推测,00402BDE处的Str1不是-cc就是-re。接下来的逻辑关系与上述分析大致相同。

 

 

 
 

Lab 9-2

 

先strings:

runtime error
TLOSS error
SING error
DOMAIN error
R6028
- unable to initialize heap
R6027
- not enough space for lowio initialization
R6026
- not enough space for stdio initialization
R6025
- pure virtual function call
R6024
- not enough space for _onexit/atexit table
R6019
- unable to open console device
R6018
- unexpected heap error
R6017
- unexpected multithread lock error
R6016
- not enough space for thread data
abnormal program termination
R6009
- not enough space for environment
R6008
- not enough space for arguments
R6002
- floating point not loaded
Microsoft Visual C++ Runtime Library
Runtime Error!
Program:
...
<program name unknown>
GetLastActivePopup
GetActiveWindow
MessageBoxA
user32.dll
Y6@
]6@
WaitForSingleObject
CreateProcessA
Sleep
GetModuleFileNameA
KERNEL32.dll
WSASocketA
WS2_32.dll
GetCommandLineA
GetVersion
ExitProcess
TerminateProcess
GetCurrentProcess
UnhandledExceptionFilter
FreeEnvironmentStringsA
FreeEnvironmentStringsW
WideCharToMultiByte
GetEnvironmentStrings
GetEnvironmentStringsW
SetHandleCount
GetStdHandle
GetFileType
GetStartupInfoA
HeapDestroy
HeapCreate
VirtualFree
HeapFree
RtlUnwind
WriteFile
HeapAlloc
GetCPInfo
GetACP
GetOEMCP
VirtualAlloc
HeapReAlloc
GetProcAddress
LoadLibraryA
MultiByteToWideChar
LCMapStringA
LCMapStringW
GetStringTypeA
GetStringTypeW
cmd

 

结合api调用行为图,基本上可以确定是一个远控shell后门:

 

 ida 7.0反编译看下:

 

 奶奶的,有了这个分析起来比汇编要爽太多了!!!后面这些汇编一弄,再回头看这个main,就觉得真的是柳暗花明啊!

 

1. 在二进制文件中,你看到的字符串是什么?       

首先使用peid进行查看,发现无壳。IDA打开Lab09-02.exe之后查看字符串

        可以看到有一些分配失败提示。

2. 当你运行这个二进制文件时,会发生什么?

        什么都不会发生。

3. 怎样让恶意代码的攻击负载运行?

        首先IDA中进行静态分析

     可以看到获取当前可执行文件的路径函数,又调用了_strrchr函数查找在GetModuleFileNameA函数返回的路径中,最后一个‘\’的位置,使用_strcmp进行字符串比较,若相同则进入loc_40124C,不同则执行结束。

        使用OD动态分析,它默认加载的地址不对,ida载入看到main入口是401128
在这里插入图片描述

ctrl+g跳转到该地址
在这里插入图片描述

我的破解版本是醬紫:

 

 

f2下断点,然后执行!到了下面401133的时候,follow一下在stack上的数据,如下:

 

 

 

 

继续运行,看getmodulefilenameA的返回,我自己机器上的操作:

先设置一个断点,f2 getmodulefilenameA

 

可以看到这个函数调用的参数bufsize,pathbuffer,hmodule这三个,这个函数的返回应该是存放在pathbuffer里,所以在右侧窗口里,点击pathbuffer的follow in dump,然后就可以看到:

 

 点击后右下角可以看到19fc34处的地址空间,暂时没有数据,这很正常,

 

接下来运行完getmodulefile后看看变化,已经正常返回了结果!good!

 

 

 

继续往下运行到了:

函数参数:

 

 

 

 不知道名字,看下ida:

 

 看来是在寻找 \ 字符串

该函数调用完成以后,返回值在eax里

 

 我自己看到的:

 

 

 

 继续往下:到1236,看看获取到的字符串都是什么:

还是在ida里对应下,看到该函数是strcmp!

 

 

        在执行到00401236处的字符串比较函数时,注意栈上的两个字符串,就是 _strcmp所需的字符串参数 !函数input看stack 2个参数和ouput!

 

 看來是返回1了!

 

Lab09-02.exe为GetModuleFileNameA函数和_strrchr函数所获取的,ocl.exe为固定的。所以比较失败,程序会直接结束,也就是因为这样,程序运行后什么都不会发生。为了继续使得程序执行,更改Lab09-02.exe名为ocl.exe。然後看到函數返回值EAX是0了!

 

 

 

在OD中00401240处下断点查看程序EIP

         此时EIP指向40124C。

4. 在地址0x00401133处发生了什么?

         初始化了两个字符串,Str = 1qaz2wsx3edc ;Str1 = ocl.exe  ==》stack,應該就是函數裏面的局部常量!!!因爲函数确实用这两个东西进行比较和异或解密!

5. 传递给0x00401089的参数是什么?

        IDA中找到目标函数,可知一个是int类型的ecx,一个是string类型的Str。

 

 

 

 

         然后交叉引用,找到调用的地址004012BD!

         OD中在004012BD处下断点,观察栈中内容:0012FC6C和0012FC70既是两个参数。

 

 进一步,点击follow in dump,可以看到该内存地址指向的数据是一堆乱码!==》这些技巧要会啊!

 

 

 

 

也就说明了恶意代码作者使用了加密!

 6. 恶意代码使用的域名是什么?

        IDA中跟进004012BD处的sub_401089函数,能够看出这个是for循环的结构 。

       OD中步进该函数退出的结果,EAX就是返回值:

 

 

         观察eax可知域名为www.practicalmalwareanalysis.com。

7. 恶意代码使用什么汇编函数来混淆域名?

        观察问题6中的for循环,这就是for循环中的主体执行语句,可以看到有很多逻辑异或操作。所以程序使用Str参数来混淆域名。

反汇编成C看看吧,就清晰多了!

 其传入的是2个字符串的地址。一个是密文的,这么看来另一个应该是秘钥了

 

最后一个问题,createprocessA的作用!

 

 

 就是对应401000函数

他把之前创建的套接字作为参数传了进去:

 进入后,把标准输入,标准输出和标准错误填充为socket

 创建了cmd进程植入反向shell。


 
Q8恶意代码在0x0040106e处调用CreateProcessA函数的意义是什么

 

 

 

 

真正olldbg运行的时候,发现:会在connect后运行1代码,而无法到2,因此我使用了nop填充1的代码,强制其到2执行:

 

 强制的方法:

 

 效果:

然后就可以进入createProcessA了!但是cmd窗口还是没有出现。。。尼玛,发现是有一个设置:

 

 

说是这个参数控制显示cmd窗口,然后我强制修改为1:

 

运行的时候,还是没有弹出cmd。。。真尼玛郁闷,难道是socket本身的问题?反弹shell,而不是正向shell,所以没有开启?。。。有高手知道的话可以吼一声。。。

 


A8.恶意代码设置stdout. stderr和stdin的句柄到socket(被用在CreateProcessA的STARTUPINFO结构中)。由于用cmd作为CreateProcessA的参数调用CreateProcessA,因此通过绑定一一个套接字与命令shell来创建逆向shell!

 

Lab 9-3

1. Lab09-03.exe导入了那些DLL?

        peid查壳发现无壳,StudyPE打开二进制文件。

       

 

IDA里看下调用图,

反汇编看下全局情况:

 

可以看到是使用了dll load来干坏事,最后是创建了一个计划任务。做逆向分析,最重要的就是全局视野,先整体扫一遍,然后再ollydbg去分析细节!

 

一共六个:KERNEL32.dll;NETAPI32.dll;DLL1.dl1;DLL2.dll;DLL3.dll;user32.dll
直接查看到四个:往下翻,看到DLL3.dll,带着个LoadLibraryA。于是接着找别的LoadLibraryA,能够看到还有个user32.dll

 

再使用IDA打开二进制文件,找到导入模块中的LoadLibraryA函数(该函数将指定的模块加载到调用进程的地址空间中,通常被恶意软件用来加载DLL)双击该函数并查看其交叉引用。

         发现有两处调用了LoadLibraryA,跟进分析

         可以看到分别加载了DLL3.dll和user32.dll,所以一共导入了6个DLL。

2. 3个DLL要求的基地址是多少?

        3个DLL基地址都是10000000。

PEID里也可以看:

 

 

3. 当使用OllyDbg调试Lab09-03.exe时,为3个Dll分配的基地址是什么? 

        IDA中分析Lab09-03.exe,查看内存窗口。

 

 

 

      DLL2基地址为003D0000,DLL1基地址为10000000。这与上一题StudyPE中查看的结果不同,这是由于PE装载所导致的。

我自己机器看到的如下,点击M(memory):

 

 

 

同时,不同操作环境地址也可能不同。DLL3是通过LoadLibraryA动态加载的,OD中在0040103C后面下断点,单步步过之后再次查看内存窗口。

 

 

 

 

 

 

 

         DLL3基地址为00440000。

4. 当Lab09-03.exe调用DLL1.dll中的一个导入函数是,这个导入函数都做了些什么?


        IDA打开DLL1.dll,找到DLL1Print函数。发现该函数调用sub_10001038之前压入了两个参数,其中一个是字符串"DLL 1 mystery data %d\n",一个是dword_10008030中的内容。通过%d推断sub_10001038是一个输出函数,dword_10008030既是输出的数据。

         双击dword_10008030查看其交叉引用,跟进第一条条目查看(是谁写了这个数据!)。dword_10008030既是GetCurrentProcessId函数的返回值,也就是当前进程的Pid。

         所以Dll1Print函数就是打印出 DLL 1 mystery data "进程id"。

 

运行看下吧:

 

 

 设置dllprint断点,然后step into:

 

 和ida里看到的是一样的:

 

 运行完该函数,控制台打印:

 

 

 

5. 当Lab09-03.exe调用WriteFile函数时,它写入的文件名是什么?

        首先在IDA中找到WriteFIle函数,其中0040102B处的ecx是WriteFile要写入的文件句柄参数,找到ecx的内容,也就找到了写入的文件名。不难发现ecx就是DLL2ReturnJ函数的返回值。

         IDA打开DLL2.dll,定位到DLL2ReturnJ函数。发现dword_1000B078处的内容既是函数返回值,双击dword_1000B078查看其交叉引用。

         跟进第一条条目,发现CreateFileA函数创建了一个temp.txt文件。所以WriteFIle函数写入的文件名就是temp.txt。 ==》这种题还是容易跟踪的,就是细心些,熟悉EAX的作用!

 6. 当Lab09-03.exe使用NetScheduleJobAdd函数创建一个job时,从哪里获取第二个参数的数据?

        IDA中定位到调用NetScheduleJobAdd处,第二个参数即为ecx所代表的Buffer,该参数是指向描述要提交的job的AT_INFO结构的指针。在Lab09-03.exe的分析中没有看到对[ebp+Buffer]的赋值,但是在00401068处看到对DLL3GetStructure函数的调用,结合NetScheduleJobAdd参数来猜测,第二个参数可能由DLL3中的DLL3GetStructure获取。

         IDA打开DLL3,定位到DLL3GetStructure函数,反汇编后的:

 

buffer数据如何被改变的,看下:

 

 也就确定了*a1是被赋值改变了buffer数据!

 

 

看到对内存中dword_1000B0A0的处理,查看此处的交叉引用。

         跟进第一条条目。

         可以看到此处是一些数据的赋值,该区域也就是问题答案。NetScheduleJobAdd函数的第二个参数是一个结构体_AT_INFO,在IDA中结构体窗口中增加该结构体:点击Insert,选择 Add standard structure,选择_AT_INFO。

       然后点击1000B0A0处进入内存窗口, 点击Edit下的Struct var,然后选择刚刚添加的结构体。

        然后回到刚才分析的1000B0A0处IDA可以识别出该结构体。

         其中AT_INFO结构体

         所以NetScheduleJobAdd函数的第二个参数来自DLL3中的DLL3 GetStructure函数。

7. 在运行或调试Lab09-03.exe时,你会看到Lab09-03.exe打印出三块神秘数据。三个神秘数据分      别是什么?

        DLL1打印的数据第四问中以分析过。IDA中分析Lab09-03.exe时,可以看到分别对DLL2Print和DLL3Printhh函数的调用。

         IDA打开DLL2,定位到DLL2Print函数。同第四问中分析的一样,可以看到在调用sub_1000105A函数前压入了两个参数:"DLL 2 mystery data %d\n"和eax。

         查看dword_1000B078处的交叉引用。

         跟进第一条条目。

         可以看到dword_1000B078存放的既是对temp.txt文件创建后的句柄。

        IDA打开DLL3,定位到DLL3Print。

         查看offset WideCharStr处的交叉引用并跟进。

         MultiByteToWideChar函数将字符串映射到 UTF-16(宽字符)字符串,10001004处将ping www.malwareanalysisbook.com在内存中的偏移地址保存,然后利用MultiByteToWideChar函数将刚才的偏移地址进行字符串转换,返回值既是WideCharStr。

        DLL1中的神秘数据是当前进程的PID。

        DLL2中的神秘数据是temp.txt的句柄。

        DLL3中的神秘数据是ping www.malwareanalysisbook.com在内存中的地址。

 
posted @ 2022-10-03 20:42  bonelee  阅读(871)  评论(0编辑  收藏  举报