
本工具实现对微软数字签名的检查和系统文件的可信性验证,界面如下:
点击下载数字签名检测工具
V1.0
killer (killer<2>unnoo.com)
Date:2006-11-20
一、病毒描述:
含有病毒体的文件被运行后,病毒将自身拷贝至系统目录,同时修改注册表将自身设置为开机启动项,并遍历各个驱动器,将自身写入磁盘根目录下,增加一个
Autorun.inf文件,使得用户打开该盘时激活病毒体。随后病毒体开一个线程进行本地文件感染,同时开另外一个线程连接某网站下载ddos程序进行发动恶意攻击。
二、病毒基本情况:
[文件信息]
病毒名: Virus.Win32.EvilPanda.a.ex$
大 小: 0xDA00 (55808), (disk) 0xDA00 (55808)
SHA1 : F0C3DA82E1620701AD2F0C8B531EEBEA0E8AF69D
壳信息: 未知
危害级别:高
病毒名: Flooder.Win32.FloodBots.a.ex$
大 小: 0xE800 (59392), (disk) 0xE800 (59392)
SHA1 : B71A7EF22A36DBE27E3830888DAFC3B2A7D5DA0D
壳信息: UPX 0.89.6 - 1.02 / 1.05 - 1.24
危害级别:高
三、病毒行为:
Virus.Win32.EvilPanda.a.ex$ :
1、病毒体执行后,将自身拷贝到系统目录:
%SystemRoot%\system32\FuckJacks.exe
2、添加注册表启动项目确保自身在系统重启动后被加载:
键路径:HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
键名:FuckJacks
键值:"C:WINDOWS\system32\FuckJacks.exe"
键路径:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
键名:svohost
键值:"C:WINDOWS\system32\FuckJacks.exe"
3、拷贝自身到所有驱动器根目录,命名为Setup.exe,并生成一个autorun.inf使得用户打开该盘运行病毒,并将这两个文件属性设置为隐藏、只读、系统。
C:autorun.inf 1KB RHS
C:setup.exe 230KB RHS
4、关闭众多杀毒软件和安全工具。
5、连接*****.3322.org下载某文件,并根据该文件记录的地址,去www.****.com下载某ddos程序,下载成功后执行该程序。
6、刷新bbs.qq.com,某QQ秀链接。
7、循环遍历磁盘目录,感染文件,对关键系统文件跳过,不感染Windows媒体播放器、MSN、IE
等程序。
Flooder.Win32.FloodBots.a.ex$ :
1、病毒体执行后,将自身拷贝到系统目录:
%SystemRoot%\SVCH0ST.EXE
%SystemRoot%\system32\SVCH0ST.EXE
2、该病毒后下载运行后,添加注册表启动项目确保自身在系统重启动后被加载:
键路径:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
键名:Userinit
键值:"C:WINDOWS\system32\SVCH0ST.exe"
3、连接ddos2.****.com,获取攻击地址列表和攻击配置,并根据配置文件,进行相应的攻击。
配置文件如下:
www.victim.net:3389
www.victim.net:80
www.victim.com:80
www.victim.net:80
1
1
120
50000
四、解决方案:
1、使用超级巡警可以完全清除此病毒和恢复被感染的文件。
2、推荐在清除时先使用超级巡警的进程管理工具结束病毒程序,否则系统响应很慢。
3、中止病毒进程和删除启动项目请看论坛相关图片。
版权所有:数据安全实验室
http://www.dswlab.com
http://www.unnoo.com
Copyright(c) DSW Lab All rights reserved
风险评估是风险管理的重要组成部分,要想更好地理解风险评估,首先要了解风险管理。
风险管理以可接受的费用识别、控制、降低或消除可能影响信息系统的安全风险的过程。是一个识别、控制、降低或消除安全风险的活动,通过风险评估来识别风险大小,通过制定信息安全方针,采取适当的控制目标与控制方式对风险进行控制,使风险被避免、转移或降至一个可被接受的水平。
本白皮书描述了大成天下安全服务体系中的一个重要部分——风险评估服务。本文主要面向企业的技术决策者、安全维护人员和基础结构工程人员。
点击下载《大成天下风险评估服务技术白皮书
v1.0》
安全加固是对信息系统中的主机系统(包含运行在主机上的各种软件系统)与网络设备的脆弱性进行分析并修补。另外,安全加固同时包括了对主机系统的身份鉴别与认证、访问控制和审计跟踪策略的增强。
加固的主要目标包括以下两点:
解决目标系统在安全评估中发现的技术性安全问题;要求在修补加固完全成后,所有被加固的目标系统不再存在高风险漏洞和中风险漏洞(高风险漏洞和中风险漏洞,根据CVE标准定义)。对相关的漏洞修补加固与现有应用冲突或已被证实会导致不良后果的情况除外。
对系统性能进行优化配置,杜绝系统配置不当而出现的弱点。
修补加固内容不能影响目标系统所承载的业务运行;
修补加固不能严重影响目标系统的自身性能;
修补加固操作不能影响与目标系统以及与之相连的其它系统的安全性,也不能造成性能的明显下降。
大成天下信息技术有限公司的技术研究人员对网络基础设施、系统与网络应用安全具有深入研究,研究范围包括网络设备及安全设备(交换机、路由器、防火墙、入侵检测系统等)、操作系统平台(Windows、AIX、HP-UX、Solaris、IRIX、Linux等)。有能力并且多次完成下列各项工作:
- 渗透测试(Penetration testing)大成科技的信息与网络安全培训具备如下特点:
- 网络架构评估与设计(Architecture review and design)
- 应用审计(Application audit)
- 源代码审计(Source code review)
- 黑箱测试(Online or Binary Black box testing)
- 审计、追踪与数据恢复(Forensics)
- 协议分析(Protocol analysis)
- 授课人员安全实战经验丰富,课件带有大量案例;
- 寓教于乐,具备充分的实验和游戏机会;
深圳市大成天下信息技术有限公司是一家专业从事网络安全产品与服务的高科技公司。凭借多年的从业经验,大成科技聚集了一批优秀的专业人才,在华南信息安全领域中具有独到的地位。
目前,大成科技的研究人员通过多年的专业安全服务经验,开发出包括游刃基线安全系统、铁卷信息监控平台等多款产品,涉及的研究领域涵盖安全评估、内容安全、接入安全等多方面,并取得多项科研技术成果。
作为专业信息安全技术与产品提供商,大成天下致力于利用自身的信息安全专业知识和经验,以帮助客户成功保障他们的资产安全。
本白皮书描述了大成天下安全评估服务体系中的一个重要部分——渗透测试服务。本文主要面向企业的技术决策者、安全维护人员和基础结构工程人员。
点击下载《大成天下渗透测试服务技术白皮书》
前些时候考虑企业秘密保护时,认为陷阱网络能够在其中发挥一定的作用,因此做了些构思,基于一定的访问控制策略,违规者发送的数据将被透明地转发至陷阱主机,但对正常操作者毫无影响。
访问控制策略包括以下几种:
1、基于时间的控制;这几种访问控制还能够在一定程度上区分出“违规者”、“渗透者”、“试探者”和“攻击者”,并且根据不同分类,转发至不同的陷阱网络中。例如:对内部违规者,可以是一台“内容级”的陷阱主机,主机上存放着部份“关键数据”;但对外部扫描者,则陷阱网络可是是一个Honeyd的“机群”,用来迷惑攻击者。
2、基于协议和开放端口的控制;
3、基于IP地址的控制;
4、基于扫描和攻击的控制;
安全评估中数据库评估是很重要的一个环节,但国内在 sybase
安全方面的资料极为匮乏,希望这篇文档能够对初学者起到基本指引的作用。
全文请参见《Sybase数据库评估指南
v1.0》(471.1 KB)
渗透测试(Penetration
Test)是指安全工程师尽可能完整地模拟黑客使用的漏洞发现技术和攻击手段,对目标网络/系统/主机/应用的安全性作深入的探测,发现系统最脆弱的环节的过程。渗透测试能够直观的让管理人员知道自己网络所面临的问题。
本文用尽量简洁的方式说明网络安全评估中最困难的环节—渗透测试的操作过程,希望读者能够揭开其神秘面纱。能够组织甚至操作一次企业内部的Penetration
Testing。
详细内容请参考《渗透测试操作实务
v1.0》
网络安全风险评估已经从几年前阳春白雪的状态,演化为当前企业/组织信息与网络安全建设前期通常会考虑进行的一项工作。但评估的方法、效果比起以往,是否有所提升?
就我所见,当前安全市场上主流的评估厂商提供的服务,大多存在以下几方面问题:
1、妄谈管理(用户选中安全公司,是因为他们懂安全,而不是因为他们懂管理);因此,这里提出的CWVE方法,实际上与OCTAVE类似,脆弱性评估不变(这是安全公司的核心技术所在),但有以下几个特点:
2、盲目量化(以为数字能说明一切,自己“定义”了量化标准和算法);
3、千人一面(评估与业务脱节,一个评估方案放之四海皆准,甚至一个评估报告也是放之四海皆准);
1、以业务流为核心,是简单资产盘点的深化;给出《采用 CWVE 方法进行安全风险评估》的幻灯片,希望朋友们看过以后,能够给出些建议。
2、以事件评估与沙盘推演替代威胁评估,操作起来不再那么虚无飘渺;
3、简化的顾问咨询过程,结论中以“制度”来推进管理,更具可操作性;
卡巴斯基反病毒软件(Kaspersky Antivirus),以前叫AntiViral Toolkit
Pro(AVP),出于习惯和简单,这里一律称为AVP或KAV。
学习AVP的检测办法的意义一方面在于AVP的检测方法是经过理论验证和实践考验的科学合理的方法,另外DOS年代过来的朋友对于反病毒有过这样的经验:“机子感染病毒了?好,请用干净无毒的系统盘启动,然后全盘查杀。”,我记得CIH横行那会,一个朋友让我帮他清除病毒,说病毒是国内某知名
AV
报的,启动该AV杀了一遍还有,而且该AV自己的监控报自己也感染了CIH,我听了后告诉他用干净的启动盘启动系统全盘查杀。虽然这是一个办法,但事实上反病毒软件为什么不直接做到可以内存检测并清除病毒呢。而这是完全可以做到的,对于内存检测/清除驻留型病毒的方法,就我所知最早AVP开始使用。
一、检测方法:
在AVP病毒库中,有几种特征记录,其中一种是内存特征,这是AVP用来检测查杀内存驻留型病毒的特征集,AVP对内存驻留的感染式病毒采用了一些单独的检测方法。
AVP通过在病毒库中记录的扫描方法和地址偏移来扫描内存中驻留的感染式病毒,从地址偏移开始进行逐字节匹配,当匹配到匹配字节的时候,即:
Segm:Offset + byte offset =
record:Byte,然后AVP开始计算由库记录指定长度的特征码,如果恰好匹配库中的记录的话,将显示对应的病毒消息,同时根据库的修复记录所指定的修复长度、和修复字节中的内容,进行内存修复,确保修复后,使得原病毒失去活性。
此记录结构包含的字段主要有:
病毒名
搜索方法:绝对地址扫描、专用模块...
地址偏移: 段+偏移
匹配字节
特征长度
特征
专用处理过程:Obj_Link
处理偏移地址
处理字节长度:一般小于10
修复字节
cmp ah,3dh编译后应该是这个样子:
jzshort @@Infect_File;截获3d号Dos功能
@@JmpOldInt21:
cli
JmpFar db 0eah
@@Infect_File:
....
13B6:0100 80FC 3DCMPAH,3Dh对于这个病毒的检测和清除,我们生成一记录,这个病毒记录在AVP库record中,可以是这种形式,它完全可以检测和解除该病毒的活性:
13B6:0104 74 xx JEInfect_File
13B6:0107 FA CLI
13B6:0108 xx xx XXX
搜索方法:中断跟踪通过这样一个检测、修复库记录,AVP就可以检测和修复内存中驻留的活性病毒,然后在通过单独的文件病毒检测/修复等处理过程来全面清除磁盘文件中的病毒。
地址偏移:1000:0000
匹配字节:80FC
特征长度:6
特征:xxxxxxxx
专用处理过程:NULL
处理偏移地址:3
处理字节长度:2
修复字节:90 90
作者:黄鑫(glacier②unnoo.com)
对木马类程序处理多了,就渐渐觉得静/动态手工分析过程在很大程度上都是重复劳动。总要先花半个钟头了解程序特性,手工分析时还生怕漏掉某项隐蔽的关键操作,导致最终清除不彻底。其实只要在主动安装木马的时候将API调用序列及相应参数做完整记录,就能极大减轻分析和清除木马的工作量。
以前曾写过一个利用 API HOOKING
原理记录可疑程序对文件、注册表、服务和网络操作的小工具。API HOOKING
方式的优点在于,当调用 CreateFile 时可将文件名与句柄关联,等调用
WriteFile 对句柄操作时便能轻易取到文件名,对 hKey、socket
等句柄操作亦是如此。但该方式的缺点也显而易见,首先必须为每个感兴趣的
API 函数编写代码,“体力工作”繁重;其次我们不可能 HOOK 所有的 API
函数,由于缺乏完整的 API
调用序列作参考,在分析日志时很可能漏掉某些小动作。
另一种思路是采用调试技术,在所有被引入的 DLL
的各函数入口处预先设置断点,调试期间再通过堆栈信息获取参数。IDA pro
和 OllyDbg
都可用于动态调试,同时还提供了脚本/插件功能。上周在北京开会的时候,我利用酒醒的时间写了一个简单的
OllyDbg 插件,仅从 CALL 指令处通过 ESP
指针获取8个函数参数,不对函数返回后的 EAX
及堆栈内容进行记录,在对普通(未加壳)程序的测试中效果还算理想。只要先在“Search
for -> All intermodular calls”窗口中执行“Set breakpoint on
every command”设置断点,再运行插件的“Fast
trace”功能即可。日志文件片断如下:
-------------------------------------------------------------------
004099EC: CALL DWORD PTR
DS:[<&KERNEL32.GetModuleFileNameA>]
(kernel32.GetModuleFileNameA)
-------------------------------------------------------------------
ESP+00 (0012F704): 00000000
ESP+04 (0012F708): 0012F824 ""
ESP+08 (0012F70C): 00000104 00000104 ???
ESP+0C (0012F710): 0012FA6D ""
ESP+10 (0012F714): 00000001 00000001 ???
ESP+14 (0012F718): 00000000
ESP+18 (0012F71C): 575C3A43 575C3A43 ???
ESP+1C (0012F720): 4F444E49 4F444E49 ???
-------------------------------------------------------------------
00409A00: CALL DWORD PTR DS:[<&KERNEL32.CopyFileA>]
(kernel32.CopyFileA)
-------------------------------------------------------------------
ESP+00 (0012F704): 0012F824 "E:\trojan.exe"
ESP+04 (0012F708):
0012F71C "C:\WINDOWS\system32\trojan.exe"
ESP+08 (0012F70C): 00000000
ESP+0C (0012F710): 0012FA6D ""
ESP+10 (0012F714): 00000001 00000001 ???
ESP+14 (0012F718): 00000000
ESP+18 (0012F71C): 575C3A43 575C3A43 ???
ESP+1C (0012F720): 4F444E49 4F444E49 ???
-------------------------------------------------------------------
00409A94: CALL DWORD PTR
DS:[<&ADVAPI32.OpenSCManagerA>]
(ADVAPI32.OpenSCManagerA)
-------------------------------------------------------------------
ESP+00 (0012F704): 00000000
ESP+04 (0012F708): 00000000
ESP+08 (0012F70C): 000F003F 000F003F ???
ESP+0C (0012F710): 0012FA6D ""
ESP+10 (0012F714): 00000001 00000001 ???
ESP+14 (0012F718): 00000000
ESP+18 (0012F71C): 575C3A43 575C3A43 ???
ESP+1C (0012F720): 4F444E49 4F444E49 ???
-------------------------------------------------------------------
00409ACF: CALL DWORD PTR
DS:[<&ADVAPI32.CreateServiceA>]
(ADVAPI32.CreateServiceA)
-------------------------------------------------------------------
ESP+00 (0012F6DC): 0014F9C0
F8 F9 14 00 98 BA DC FE 00 00 00 00 B4 F9 CC 53
...............S
82 6C FC 42 BF 8C 55 14 00 44 14 F4 AB AB AB AB
.l.B..U..D......
AB AB AB AB EE FE EE FE 00 00 00 00 00 00 00 00
................
20 00 07 00 09 07 18 00 58 FA C3 77 EF CD AB
89 .......X..w....
00 00 01 00 01 00 00 00 00 00 00 00 00 00 00 00
................
00 00 00 00 00 00 00 00 05 00 00 00 01 00 00 00
................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
................
06 00 00 00 0A 00 00 00 00 00 00 00 30 FB 14 00
............0...
ESP+04 (0012F6E0): 0042008C "trojan"
ESP+08 (0012F6E4): 004200C0 "Back door for
testing"
ESP+0C (0012F6E8): 000F01FF 000F01FF ???
ESP+10 (0012F6EC): 00000120 00000120 ???
ESP+14 (0012F6F0): 00000002 00000002 ???
ESP+18 (0012F6F4): 00000001 00000001 ???
ESP+1C (0012F6F8):
0012F71C "C:\WINDOWS\system32\trojan.exe -start"
......
这种简单粗糙的日志对我来说已经够用了。若希望以更友好的形式显示参数信息,就必须有一些数据文件来描述各
API 函数的调用方式、返回值类型、参数个数等内容。比如这样:
int LoadLibraryA([in] char *lpLibFileName);
int LoadLibraryW([in] wchar *lpLibFileName);
void *GetProcAddress([in] int hModule, [in] char
*lpProcName);
int GetModuleFileNameA([in] int hModule, [out] char
*lpFilename, [in] int nSize);
int GetModuleFileNameW([in] int hModule, [out] wchar
*lpFilename, [in] int nSize);
编写一个简单的词法解析模块直接解析 VC 自带的 .h
文件,对使用者来说就更省事了。经过参数类型解析后的输出信息会好看很多:
------------------------------------------------------
004099F2 -> GetModuleFileNameA(
int hModule: 0 (unsigned = 0 / hex
= 0),
char* lpFilename: [0012F824] = "",
int nSize: 260 (unsigned = 260 /
hex = 104),
13 << results
int hModule: 0 (unsigned = 0 / hex
= 0),
char* lpFilename: [0012F824] =
"e:\trojan.exe" in stack of Thread,
int nSize: 260 (unsigned = 260 /
hex = 104)
);
------------------------------------------------------
00409A06 -> CopyFileA(
char* lpExistingFileName: [0012F824] =
"e:\trojan.exe" in stack of Thread,
char* lpNewFileName: [0012F71C] =
"C:\WINDOWS\system32\trojan.exe" in stack of Thread,
int bFailIfExists: 0 (unsigned = 0 / hex
= 0),
1 << results
char* lpExistingFileName: [0012F824] = "",
char* lpNewFileName: [0012F71C] = "",
int bFailIfExists: 0 (unsigned = 0 / hex
= 0)
);
------------------------------------------------------
00409A9A -> OpenSCManagerA(
char* lpMachineName: [00000000] =
(null),
char* lpDatabaseName: [00000000] =
(null),
int dwDesiredAccess: 983103 (unsigned =
983103 / hex = F003F),
1374656 << results
char* lpMachineName: [00000000] = "",
char* lpDatabaseName: [00000000] = "",
int dwDesiredAccess: 983103 (unsigned =
983103 / hex = F003F)
);
------------------------------------------------------
00409AD5 -> CreateServiceA(
int hSCManager: 1374656 (unsigned =
1374656 / hex = 14F9C0),
char* lpServiceName: [0042008C] = "trojan"
in main image (.data),
char* lpDisplayName: [004200C0] = "Back
door for testing" in main image (.data),
int dwDesiredAccess: 983551 (unsigned =
983551 / hex = F01FF),
int dwServiceType: 288 (unsigned = 288 /
hex = 120),
int dwStartType: 2 (unsigned = 2 / hex
= 2),
int dwErrorControl: 1 (unsigned = 1 / hex
= 1),
char* lpBinaryPathName: [0012F71C] =
"C:\WINDOWS\system32\trojan.exe -start" in stack of Thread,
char* lpLoadOrderGroup: [00000000] =
(null),
int* lpdwTagId: 00000000,
char* lpDependencies: [004201C4] = "" in
main image (.data),
char* lpServiceStartName: [00000000] =
(null),
char* lpPassword: [00000000] =
(null),
1370392 << results
int hSCManager: 1374656 (unsigned =
1374656 / hex = 14F9C0),
char* lpServiceName: [0042008C] = "",
char* lpDisplayName: [004200C0] = "",
int dwDesiredAccess: 983551 (unsigned =
983551 / hex = F01FF),
int dwServiceType: 288 (unsigned = 288 /
hex = 120),
int dwStartType: 2 (unsigned = 2 / hex
= 2),
int dwErrorControl: 1 (unsigned = 1 / hex
= 1),
char* lpBinaryPathName: [0012F71C] = "",
char* lpLoadOrderGroup: [00000000] = "",
int* lpdwTagId: 00000000,
char* lpDependencies: [004201C4] = "",
char* lpServiceStartName: [00000000] = "",
char* lpPassword: [00000000] = ""
);
......
dumbug 是一个开源的 API TRACING 工具,但被设计为仅对 trace
文件中定义的 API 调用进行跟踪。要想通过原始的 dumbug 获得完整 API
调用序列,工作量一点也不比 API HOOKING
方式小。而且就分析木马程序来说,我们并不需要记录 kernel32.dll
等系统链接库内部的 API 调用序列,所以还应根据 EXE 和 DLL
的入口地址、代码段长度进行过滤,最大限度减少冗余信息。在 dumbug
中,只要为 Tracer 对象的 ActivateTraces()
方法添加一些代码,并在其他地方也做相应的小修改,就可以输出上面的结果了。
附1 - dumbug 的源代码可以从这里获得:
http://www.phenoelit.de/dumbug/dumbugVegasRelease.zip
附2 - 简单的 ApiTracing-plugin for OllyDbg 源代码:
// ApiTracing.c
#define STRICT // Avoids some type
mismatches
#include <windows.h>
#include <stdio.h>
#include <dir.h>
#include "plugin.h"
#define VERSIONHI 1 // High plugin
version
#define VERSIONLO 0 // Low plugin
version
#define LOG_FILENAME "TraceApi.log" // Log filename
static HINSTANCE hinst; // DLL instance
static BOOL bFastTracing = TRUE;
static BOOL bStartTrace = FALSE;
int Execute(char *text,char *answer);
BOOL WINAPI DllEntryPoint(HINSTANCE hi, DWORD reason, LPVOID
reserved)
{
FILE *fLog;
if (reason == DLL_PROCESS_ATTACH) {
hinst = hi; // Mark plugin
instance
fLog = fopen(LOG_FILENAME, "w");
if (fLog) {
fprintf(fLog, "API tracing plugin v%i.%02i, written
by glacier_at_xfocus.org\n",
VERSIONHI, VERSIONLO);
fclose(fLog);
}
}
return 1; // Report success
}
// Report plugin name and return version of plugin
interface.
extc int _export cdecl ODBG_Plugindata(char
shortname[32])
{
strcpy(shortname, "API tracing"); // Name of command line
plugin
return PLUGIN_VERSION;
}
extc int _export cdecl ODBG_Plugininit(int ollydbgversion, HWND
hw, ulong *features)
{
// This plugin uses some newest features,
// check that version of OllyDbg is correct.
if (ollydbgversion < PLUGIN_VERSION)
return -1;
return 0;
}
extc void _export cdecl ODBG_Pluginmainloop(DEBUG_EVENT
*debugevent) {
}
// Function adds items to main OllyDbg menu
(origin=PM_MAIN).
extc int _export cdecl ODBG_Pluginmenu(int origin, char
data[4096], void *item)
{
if (origin != PM_MAIN)
return 0; // No pop-up menus in
OllyDbg's windows
strcpy(data, "0 &Fast trace,1 &Slow trace|2
&About");
return 1;
}
// Receives commands from main menu.
extc void _export cdecl ODBG_Pluginaction(int origin, int
action, void *item)
{
char szLine[MAX_PATH] = {0};
if (origin != PM_MAIN)
return;
switch (action) {
case 0: // Fast tracing
bFastTracing = TRUE;
bStartTrace = TRUE;
Sendshortcut(PM_MAIN, 0, WM_KEYDOWN, 0, 0,
VK_F9);
break;
case 1: // Slow tracing
bFastTracing = FALSE;
bStartTrace = TRUE;
Sendshortcut(PM_MAIN, 0, WM_KEYDOWN, 0, 0,
VK_F7);
break;
case 2: // "About", displays
plugin info
sprintf(szLine, "API tracing plugin v%i.%02i",
VERSIONHI, VERSIONLO);
MessageBox(0, szLine, "API tracing",
MB_OK|MB_ICONINFORMATION);
break;
default: break;
}
}
// User opens new or restarts current application.
extc void _export cdecl ODBG_Pluginreset(void)
{
bStartTrace = FALSE;
}
extc int _export cdecl ODBG_Pluginclose(void)
{
return 0;
}
extc void _export cdecl ODBG_Plugindestroy(void)
{
}
// 记录二进制内容
void LogBinToFile(char *szFileName, const char *pBuf, int
nSize)
{
FILE *fLog;
int i, j;
unsigned const char *ptr = (unsigned const char
*)pBuf;
fLog = fopen(szFileName, "a+");
if (!fLog) return;
if (nSize == 0)
nSize = strlen(pBuf);
for (i=0; i<nSize; i=i+0x10) {
fprintf(fLog, "\t\t");
for (j=i; j<i+0x10 && j<nSize; j++)
fprintf(fLog, "%02X ", ptr[j]);
fprintf(fLog, "\t");
for (j=i; j<i+0x10 && j<nSize; j++)
{
if (IsCharAlpha(ptr[j]) || (ptr[j]>=0x20
&& ptr[j]<0x7F))
fprintf(fLog, "%c", ptr[j]);
else
fprintf(fLog, "%c", '.');
}
fprintf(fLog, "\n");
}
fclose(fLog);
}
// 格式化记录日志
void LogToFile(char *szFileName, char *szFmt, ...)
{
FILE *fLog;
char buff[1024];
va_list arglist;
va_start(arglist, szFmt);
_vsnprintf(buff, sizeof(buff), szFmt, arglist);
va_end(arglist);
fLog = fopen(szFileName, "a+");
if (!fLog) return;
fprintf(fLog, "%s", buff);
fclose(fLog);
}
// 检查是否为ASCII字符串
BOOL CheckCharAlpha(char *szLine)
{
int i = 0;
while (szLine[i]) {
if (!IsCharAlpha(szLine[i]) &&
(szLine[i]<0x20 || szLine[i]>=0x7F))
return FALSE;
i++;
}
return TRUE;
}
extc int _export cdecl ODBG_Paused(int reason, t_reg
*reg)
{
char szSrcDec[1024] = {0};
char szLine[1024] = {0};
unsigned long uEsp = 0, uAddr = 0, uTemp = 0;
int nSize = 0, i = 0;
if (!bStartTrace) return 0;
if (!reg) {
ShellExecute(0, "open", "notepad.exe", LOG_FILENAME,
NULL, SW_SHOW);
return 0;
}
// 读取断点处指令
nSize = Readcommand(reg->ip, szLine);
if (nSize > 0) {
t_disasm disasm;
// 反汇编二进制指令
Disasm(szLine, nSize, reg->ip, szSrcDec,
&disasm, DISASM_ALL, 0);
if (strstr(disasm.result, "CALL ")) { //
若为CALL指令
LogToFile(LOG_FILENAME, "\n%s\n",
"------------------------------------------------------");
LogToFile(LOG_FILENAME, "%08X: %s (%s)",
reg->ip, disasm.result, disasm.comment);
LogToFile(LOG_FILENAME, "\n%s\n",
"------------------------------------------------------");
uEsp = reg->r[4];
// 由ESP读取8个堆栈参数
uTemp = uEsp;
for (i=0; i<8; i++) {
Readmemory(&uAddr, uTemp, sizeof(uAddr),
MM_SILENT);
LogToFile(LOG_FILENAME, "\tESP+%02X (%08X):
%08X", i*4, uTemp, uAddr);
if (uAddr == 0) nSize = 0;
else nSize = Decodeascii(uAddr, szLine,
sizeof(szLine)-1, DASC_ASCII);
if (nSize > 0 &&
CheckCharAlpha(szLine)) {
LogToFile(LOG_FILENAME, "\t\t%s\n",
szLine);
}
else {
memset(szLine, 0, sizeof(szLine));
nSize = Readmemory(szLine, uAddr, 128,
MM_SILENT);
if (nSize > 0) {
LogToFile(LOG_FILENAME, "\n");
LogBinToFile(LOG_FILENAME, szLine,
nSize);
}
else
LogToFile(LOG_FILENAME, "\n");
}
uTemp += 4;
}
}
// 继续执行
if (bFastTracing)
Sendshortcut(PM_MAIN, 0, WM_KEYDOWN, 0, 0,
VK_F9);
else {
if (strstr(disasm.result, ".0")) {
Go(0, reg->ip, STEP_IN, 1, 0);
}
else {
Go(0, reg->ip, STEP_OVER, 1, 0);
}
}
}
return 0;
}
Powered by Haiwit