-
-
[原创] 默默无闻·恶意代码分析Lab5
-
发表于: 2021-4-5 06:44 6480
-
参照书籍:《恶意代码分析实战》;
文件来源:官网随书文件、或者附件中(文件密码:apebro
);;
使用工具:WinHex、CFF、StudyPE+、Exeinfo PE、Resource Hacker、Depends Walker、OD、IDA、MSDN;
只用IDA Pro分析在文件Lab05-01.dll中发现的恶意代码。这个实验的目标是给你的一个用IDA Pro动手的经验。如果你已经用IDA Pro工作过,你可以选择忽略这些问题,而将精力集中在逆向工程恶意代码上。
很显然,没有壳;
再审题,基本上都是IDA Pro的操作,看来是一次复习IDA Pro使用了。
1、DLLMain的地址是什么?
获得DLLMain的位置0x1000D02E
;
这里有一个知识点:就是这里的地址是理论上的VA,注意是理论上的,因为如果理论位置被加载了,就需要让系统重新选择一个位置,然后重定位。所以有效的地址应该是换算成RVA
2、使用Imports窗口并浏览到gethostbyname
,导入函数定位到什么地址?
获得定位0x100163CC
;
3、有多少函数调用了gethostbyname
?
共18次引用,Type处p
代表被调用,r
代表[…]
“读取”式引用,所以有9个交叉引用对gethostbyname()
进行调用;
4、将精力集中在位于0x10001757
处的对gethostbyname
的调用,你能找出哪个DNS请求将被触发吗?
这里是一个call
操作,所以向上找参数;
所以先要找到数据地址头;
将鼠标放在黄色字符串上,就能看到完整字符串;或者打开Strings窗口,检索红色框起来的字符串;
这就找到了网址,所以会对该网址发起DNS请求,获得其IP地址;
5、IDA Pro识别了在0x10001656
处的子过程中的多少个局部变量?
这个就很显然了,偏移为负的是局部变量 ;
IDA很智能的识别出了23个局部变量;
6、IDA Pro识别了在0x10001656
处的子过程中的多少个参数?
偏移为正的是参数;
IDA很智能的识别出了1个参数;
7、使用Strings窗口,来在反汇编中定位字符串\cmd.exe /c
。它位于哪?
找到字符串地址0x10095B34
;
8、在引用cmd.exe /c
的代码所在的区域发生了什么?
双击Address
地址,跳转到IDA View-A
代码;
这是个push
操作;
9、在同样的区域,在0x100101c8
处,看起来好像dword_1008E5C4
是一个全局变量,它帮助决定走哪条路径。那恶意代码是如何设置dword_1008E5C4
的呢?(提示:使用dword_1008E5C4
的交叉引用。)
得到:
由代码可知:dwPlatformId
与数字2进行比较,如果相等,al置1,也就是返回true
;
由此可以简单的判断当前操作系统的版本;
只需要查到GetVersionExA()
函数的参数类型,然后一直向上找定义,就能找到结构体类型;
10、在位于0x1000FF58
处的子过程中的几百行指令中,一系列使用memcmp
来比较字符串的比较。如果对robotwork
的字符串比较是成功的(当memcmp
返回0
),会发生什么?
终于找到了,用Graph View
看更壮观,真的好多memcmp
;
指令是个push
,大概率是一个传参操作,继续向下找call
;
注意看call下面那句,明显是平栈操作,很显然memcmp
使用的是__cdecl
调用方式;
根据题意,memcmp
返回0
;
再复习一下test
指令;
所以test eax,eax
等于and eax , eax
也就是and 0 , 0
,结果为0
,ZF位置1
。
如果ZF位为1
,jnz
指令则不跳转;
说明它查询了路径为HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\
处WorkTime
和WorkTimes
的注册表项;
有意思的是看sub_100038EE
处的函数;
这是一个隐藏的Socket
函数,所以应该是先查询注册表值,然后再发送一个网络信息;
11、PSLIST
导出函数做了什么?
最近的跳转是关联sub_100036C3
函数的返回值;
这函数很眼熟,是获取操作系统版本的;
至于2
和5
是操作系统版本号;
答案给出的是Windows Vista/7
或是Windows XP/2003/2000
;
依旧是到了sub_100038BB
;
综上所述,这两条代码路径都使用CreateToolHelp32Snapshot
函数,从字符串和API来看,是获取进程列表,通过send
将进程列表通过socket
发送出去;
12、使用图模式来绘制处对sub_10004E79
的交叉引用图。当进入这个函数时,哪个API函数可能被调用?仅仅基于这些API函数,你会如何重命名这个函数?
13、DLLMain直接调用了多少个Windows API?多少个在深度为2
时被调用?
先通过g
键跳到0x1000D02E
的DLLMain处;
右击进入Graph View
视图;
将红标处设置为2
;
14、在0x10001358
处,有一个对Sleep
(一个使用一个包含要睡眠的毫秒数的参数的API函数)的调用。顺着代码向后看,如果这段代码执行,这个程序会睡眠多久?
先通过g
键跳到0x10001358
处;
找到Sleep
函数;
15、在0x10001701
处是一个对socket
的调用。它的3个参数是什么?
16、使用MSDN页面的socket
和IDA Pro中的命名符号常量,你能使参数更加有意义吗?在你应用了修改以后,参数是什么?
选中数字,右击选择Use Symbolic Constant
,出现对话框选择OK
就好了;
这就成功了;
17、搜索in
指令(opcode 0xED
)的使用。这个指令和一个魔术字符串VMXh
用来进行VMware检测。这在这个恶意代码中被使用了吗?使用对执行in
指令函数的交叉引用,能发现进一步检测VMware的证据吗?
有两种方式:
选择Find All Occurrences
,可以列出所有匹配;
选中0x564D5868h
摁r
键可以看出字符串等于VMXh
;
看书后答案,这里涉及了反虚拟机技巧,17章的时候会有更详细的介绍;
18、将你的光标跳转到0x1001D988
处,你发现了什么?
先通过g
键跳到0x1001D988
处;
猜测是一端硬编码;
19、如果你安装了IDA Python插件(包括IDA Pro的商业版本的插件),运行Lab05-01.py
,一个本书中随恶意代码提供的PDA Pro Python脚本,(确定光标是在0x1001D988
处。)在你运行这个脚本后发生了什么?
根据题意,选择菜单File -> Script File
,选择随书文件中的Python脚本运行;
可惜我的版本并不支持python脚本,掠过掠过;
20、将光标放在同一位置,你如何将这个数据转成一个单一的ASCII字符串?
21、使用一个文本编辑器打开这个脚本。它是如何工作的?
看似东西不多,做起来也快,就是写笔记写帖子总是很慢很慢;
坚持吧,坚持总会有结果的;
共勉!
mov eax , off_10019040 ;这里是一个数据地址头
add eax , ODh ;ODh大小
push eax ;把eax压栈
mov eax , off_10019040 ;这里是一个数据地址头
add eax , ODh ;ODh大小
push eax ;把eax压栈
/
/
GetVersionEx函数获取当前运行的操作系统版本的扩展信息。
BOOL
GetVersionEx(
LPOSVERSIONINFO lpVersionInformation
/
/
pointer to version
/
/
information structure
);
/
/
GetVersionEx函数获取当前运行的操作系统版本的扩展信息。
BOOL
GetVersionEx(
LPOSVERSIONINFO lpVersionInformation
/
/
pointer to version
/
/
information structure
);
bool
sub_10003695(){
typedef struct {
/
/
通过MSDN类型溯源获得结构体完整类型;
DWORD dwOSVersionInfoSize;
DWORD dwMajorVersion;
/
/
函数没使用
DWORD dwMinorVersion;
/
/
函数没使用
DWORD dwBuildNumber;
/
/
函数没使用
DWORD dwPlatformId;
CHAR szCSDVersion[
128
];
/
/
Maintenance string
for
PSS usage
}VersionInformation;
VersionInformation.dwOSVersionInfoSize
=
0x94h
;
GetVersionExA(&VersionInformation);
return
VersionInformation.dwPlatformId
=
=
2
;
}
bool
sub_10003695(){
typedef struct {
/
/
通过MSDN类型溯源获得结构体完整类型;
DWORD dwOSVersionInfoSize;
DWORD dwMajorVersion;
/
/
函数没使用
DWORD dwMinorVersion;
/
/
函数没使用
DWORD dwBuildNumber;
/
/
函数没使用
DWORD dwPlatformId;
CHAR szCSDVersion[
128
];
/
/
Maintenance string
for
PSS usage
}VersionInformation;
VersionInformation.dwOSVersionInfoSize
=
0x94h
;
GetVersionExA(&VersionInformation);
return
VersionInformation.dwPlatformId
=
=
2
;
}
/
/
比较两个缓冲区中的字符。
int
memcmp( const void
*
buf1, const void
*
buf2, size_t count );
/
/
Return Value
/
/
返回值指示缓冲区之间的关系。
/
/
返回buf1和buf2的第一个计数字节的值关系
/
/
<
0
buf1 小于 buf2
/
/
=
0
buf1 等于 buf2
/
/
>
0
buf1 大于 buf2
/
/
比较两个缓冲区中的字符。
int
memcmp( const void
*
buf1, const void
*
buf2, size_t count );
/
/
Return Value
/
/
返回值指示缓冲区之间的关系。
/
/
返回buf1和buf2的第一个计数字节的值关系
/
/
<
0
buf1 小于 buf2
/
/
=
0
buf1 等于 buf2
/
/
>
0
buf1 大于 buf2
/
/
RegOpenKeyEx函数打开指定的注册表键。
LONG
RegOpenKeyEx(
HKEY hKey,
/
/
handle to
open
key
LPCTSTR lpSubKey,
/
/
address of name of subkey to
open
DWORD ulOptions,
/
/
reserved
REGSAM samDesired,
/
/
security access mask
PHKEY phkResult
/
/
address of handle to
open
key
);
/
/
返回值
/
/
如果函数成功执行,返回值为ERROR_SUCCESS。
/
/
如果函数失败,返回值为WINERROR.H中定义的非零错误代码。您可以使用带有 FORMAT_MESSAGE_FROM_SYSTEM标志的FormatMessage函数来获取错误的通用描述。
/
/
RegOpenKeyEx函数打开指定的注册表键。
LONG
RegOpenKeyEx(
HKEY hKey,
/
/
handle to
open
key
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
- [原创]默默无闻·恶意代码分析Lab10 13507
- [原创] 默默无闻·恶意代码分析Lab9 15340
- [原创] 默默无闻·恶意代码分析Lab7 5584
- [原创]咬文嚼字·浅说OEP和EP 16508
- [原创]默默无闻·恶意代码分析第七章 7882