利用WinDbg和wscript.exe分析JavaScript脚本

本文介绍如何使用WinDbg结合wscript.exe分析JavaScript脚本,探讨了针对不同JavaScript对象(如ActiveX和COM对象)的调试技巧,并演示了如何定位关键函数执行点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文讲的是 利用WinDbg和wscript.exe分析JavaScript脚本

介绍

攻击者经常使用JavaScript来编写恶意软件因为它系统默认解析很少被禁用。我们之前关于.NET分析的文章引起了很多关于如何使用WinDBG来分析.js文件的兴趣。在这篇文章中我们使用WinDBG及64位版本的wscript.exe来分析JavaScript。强烈建议先阅读我们以前的文章

WINDOWS系统上的对象加载

JavaScript通常需要加载外部对象来获取Windows解释器默认不包含的附加功能。这个可以通过使用ActiveObject()的API用来加载ActiveX对象或WScript.CreateObject()的API用来加载COM对象。这两个API的后台机制大同小异——加载一个外部库来启用对新对象的访问。下面是两个调用的例子

New ActiveXObject("Shell.Application");
WScript.CreateObject("Wscript.Shell");

第一点是了解哪些库是在这两个对象之后。此信息存储在注册表中首先我们需要在以下注册表名称中获取与对象名称关联的CLSIDHKEY_CLASSES_ROOT\OBJECT_NAME\CLSID. 。

以下是Shell.Application对象名称的示例

利用WinDbg和wscript.exe分析JavaScript脚本

这表明CLSID是{13709620-C279-11CE-A49E-444553540000}。有了这些信息我们可以在HKEY_CLASSES_ROOT\CLSID\{THE_CLSID}中获取对象的dll路径

利用WinDbg和wscript.exe分析JavaScript脚本

在这种情况下Shell.Application对象所在的库是shell32.dll。有了这些信息我们就可以启动WinDBG来分析对象加载和执行。

WINDBG分析

JavaScript执行的分析是通过调试wscript.exe二进制执行的。这可以使用以下命令执行

"C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\windbg.exe" 
C:\Windows\System32\wscript.exe c:\Users\User\to_be_analysed.js

技术往往是一样的

· 加载对象库时的断点;
· 对所需功能的识别和断点;
· 获取函数的参数

案例研究1ActiveX对象

第一个案例

var oShell = new ActiveXObject("Shell.Application");
var commandtoRun = "calc.exe";
oShell.ShellExecute(commandtoRun,"","","","1");

第一个任务是找到“Shell.Application”库对象位于注册表中的位置

c:\Users\user> script.py Shell.Application
Object Name: Shell.Application
CLSID: {13709620-C279-11CE-A49E-444553540000}
Description: Shell Automation Service
dll: %SystemRoot%\system32\shell32.dll

这告诉我们应该分析shell32.dll。我们来执行这个脚本并在加载库时引入一个断点

0:000> sxe ld shell32 ; g
ModLoad: 00007fff`c6af0000 00007fff`c7f27000   
C:\WINDOWS\System32\SHELL32.dll
ntdll!NtMapViewOfSection+0x14:
00007fff`c8e658a4 c3              ret
The next step is to identify the ShellExecute function:
0:000> x shell32!ShellExecute

不幸的是该函数在JavaScript和库中没有相同的名称。但是我们可以使用正则表达式来搜索它

0000> x shell32ShellExecute * 
00007fff`c6b13dd0 SHELL32ShellExecuteExWvoid
00007fff`c6b13e44 SHELL32ShellExecuteNormalvoid 
00007fff`c6cb1630 SHELL32ShellExecuteExA<no parameter info>
00007fff`c6fa8d58 SHELL32ShellExecuteRegApp<no parameter信息>
00007fff`c6bef560 SHELL32ShellExecuteW<no parameter info>
00007fff`c6cb15a0 SHELL32ShellExecuteA<no parameter info>
00007fff`c6fa9058 SHELL32ShellExecuteRunApp<no parameter info>

在我们的例子中我们可以为ShellExecuteNormal添加一个断点

0:000> bp shell32!ShellExecuteNormal
0:000> g
Breakpoint 0 hit
SHELL32!ShellExecuteNormal:
00007fff`c6b13e44 48895c2408      mov     qword ptr [rsp+8],rbx 
ss:00000029`cb56c7a0=00000029cb56cc90

我们现在可以通过RCX寄存器直接获取参数

0:000> r $t1=poi(rcx+0x18);du $t1
000001ee`350d055c  "calc.exe"

乍一看为什么偏移量为0x18并不明显。这是由于参数传递给ShellExecuteNormal是指向SHELLEXECUTEINFO结构的指针。微软的文档描述比在这些情况下结构位于偏移0x18。

案例研究2WScript Shell对象

我们来看一下第二个例子

var shell = WScript.CreateObject("Wscript.Shell");
var command = "calc.exe"; 
shell.Run(command, true, false);

如前所述第一个任务包括查找Wscript.Shell所在的库

c:\Users\user> script.py Wscript.Shell
Object Name: Wscript.Shell
CLSID: {72C24DD5-D70A-438B-8A42-98424B88AFB8}
Description: Windows Script Host Shell Object
dll: C:\Windows\System32\wshom.ocx

我们尝试识别功能名称

0:000> sxe ld wshom
0:000> g
ModLoad: 00007fff`b5630000 00007fff`b5657000   
C:\Windows\System32\wshom.ocx
ntdll!NtMapViewOfSection+0x14:
00007fff`c8e658a4 c3              ret
0:000> x wshom!*Run*
00007fff`b5640930 wshom!CUnknown::InnerUnknown::`vftable' = <no type information>
00007fff`b563d530 wshom!CUnknown::InnerUnknown::QueryInterface (<no parameter info>)
00007fff`b5648084 wshom!_IMPORT_DESCRIPTOR_ScrRun = <no type information>
00007fff`b563d570 wshom!CUnknown::InnerUnknown::Release (<no parameter info>)
00007fff`b5643d30 wshom!ScrRun_NULL_THUNK_DATA = <no type information>
00007fff`b563bbb0 wshom!CWshShell::Run (<no parameter info>)
00007fff`b5631000 wshom!CUnknown::InnerUnknown::AddRef (<no parameter info>)
00007fff`b5644518 wshom!LIBID_IWshRuntimeLibrary = <no type information>)

该函数是wshom!CWshShell::Run我们可以在此断点并检查参数

0:000> bp wshom!CWshShell::Run
0:000> g
Breakpoint 0 hit
wshom!CWshShell::Run:
00007fff`b563bbb0 48895c2408      mov     qword ptr [rsp+8],rbx 
ss:00000020`7ccfd520=0000013f3d650420
0:000> du rdx
0000013f`3d65055c  "calc.exe"

与之前的案例研究相反参数直接是一个字符串而不是一个结构因此没有必要偏移来检索参数

案例研究3WScript XMLHTTP对象

var httpStream = WScript.CreateObject("MSXML2.XMLHTTP");
httpStream.open("GET", 'http://blog.talosintelligence.com');
httpStream.send();

与MSXML2.XMLHTTP对象关联的库

c:Usersuser> script.py MSXML2.XMLHTTP
Object Name: MSXML2.XMLHTTP
CLSID: {F6D90F16-9C73-11D3-B32E-00C04F990BB4}
Description: XML HTTP
dll: %SystemRoot%\System32\msxml3.dll

我们可以使用与以前相同的技术

0:000> sxe ld msxml3
0:000> g
ModLoad: 00007fff`8dc40000 00007fff`8de68000   
C:\WINDOWS\System32\msxml3.dll
ntdll!NtMapViewOfSection+0x14:
00007fff`c8e658a4 c3              ret

这一次我们使用正则表达式在包含单词“Open”的所有API上断点

0:000> bm msxml3!*Open*
1: 00007fff`8dc43030 @!"msxml3!ErrorHelper::CHTMLWindow2::open"
breakpoint 1 redefined
1: 00007fff`8dc43030 @!"msxml3!FakeHTMLDoc::open"
2: 00007fff`8dd4c5fc @!"msxml3!HTTPStream::OpenRequest"
3: 00007fff`8dcaa407 @!"msxml3!_imp_load_CertOpenStore"
breakpoint 1 redefined
1: 00007fff`8dc43030 @!"msxml3!ErrorHelper::CHTMLWindow2::get_opener"
4: 00007fff`8dc48eb4 @!"msxml3!ContentModel::openGroup"
5: 00007fff`8dd4cb00 @!"msxml3!HTTPStream::deferedOpen"
breakpoint 1 redefined
1: 00007fff`8dc43030 @!"msxml3!ErrorHelper::CHTMLDocument2::open"
breakpoint 1 redefined
1: 00007fff`8dc43030 @!"msxml3!ErrorHelper::CHTMLWindow2::put_opener"
6: 00007fff`8dd4a050 @!"msxml3!URLMONRequest::open"
7: 00007fff`8dc8f4d0 @!"msxml3!FileStream::deferedOpen"
8: 00007fff`8dd34e80 @!"msxml3!XMLHttp::open"
9: 00007fff`8dc597e0 @!"msxml3!URLMONStream::deferedOpen"
10: 00007fff`8dc70ddc @!"msxml3!NamespaceMgr::popEntry"
11: 00007fff`8dcaa3bf @!"msxml3!_imp_load_WinHttpOpen"
12: 00007fff`8dcaa3e3 @!"msxml3!_imp_load_WinHttpOpenRequest"
13: 00007fff`8dd47340 @!"msxml3!HTTPRequest::open"
14: 00007fff`8dd47660 @!"msxml3!HTTPRequest::openWithCredentials"
15: 00007fff`8dc8f37c @!"msxml3!FileStream::open"
16: 00007fff`8dd4c128 @!"msxml3!URLStream::OpenPreloadResource"
17: 00007fff`8dd4b410 @!"msxml3!URLRequest::open"
0:000> g
Breakpoint 8 hit
msxml3!XMLHttp::open:
00007fff`8dd34e80 488bc4          mov     rax,rsp

我们看到使用的API实际上是XMLHttp::open()从我们可以获得的参数

0:000> du rdx
00000173`311a0568  "GET"
0:000> du r8
00000173`311a0578  "http://blog.talosintelligence.co"
00000173`311a05b8  "m"

这些参数是两个字符串而不是一个结构可以无偏移地检索。

案例研究4Eval函数

恶意软件作者经常使用eval函数来模糊代码执行。此功能是JavaScript本机的不需要外部库。这里是一个使用eval的例子

var test = "var oShell = new ActiveXObject(\"Shell.Application\");var commandtoRun = \"notepad.exe\"; oShell.ShellExecute(commandtoRun,\"\",\"\",\"\",\"1\");"
eval(test) 

var encoded = "dmFyIG9TaGVsbCA9IG5ldyBBY3RpdmVYT2JqZWN0KCJTaGVsbC5BcHBsaWNhdGlvbiIpO3ZhciBjb21tYW5kdG9SdW4gPSAiY2FsYy5leGUiOyBvU2hlbGwuU2hlbGxFeGVjdXRlKGNvbW1hbmR0b1J1biwiIiwiIiwiIiwiMSIpOwo="
eval(Base64.decode(encoded))

该脚本执行两种不同类型的eval调用。第一个包含一个直接执行的字符串calc.exe执行; 第二个包含用于生成要执行的代码的命令用base64编码的notepad.exe执行。

eval函数本身位于script.dll库中bp jscriptJsEval。该函数使用jscriptCOleScript :: Compile API来生成通过eval执行的JavaScript代码

0:000> sxe ld jscript;g
ModLoad: 00007fff`9e650000 00007fff`9e70c000   
C:\Windows\System32\jscript.dll
ntdll!NtMapViewOfSection+0x14:
00007fff`c8e658a4 c3              ret
0:000> bp jscript!JsEval
0:000> g
Breakpoint 0 hit
jscript!JsEval:
00007fff`9e681960 488bc4          mov     rax,rsp
0:000> u rip L50
jscript!JsEval:
00007fff`9e681960 488bc4          mov     rax,rsp
00007fff`9e681963 48895810        mov     qword ptr [rax+10h],rbx
00007fff`9e681967 48897018        mov     qword ptr [rax+18h],rsi
00007fff`9e68196b 48897820        mov     qword ptr [rax+20h],rdi
[...redacted…]
00007fff`9e681a81 488364242000    and     qword ptr [rsp+20h],0
00007fff`9e681a87 e80c3cfdff      call    jscript!COleScript::Compile
00007fff`9e681a8c 89455f          mov     dword ptr [rbp+5Fh],eax
00007fff`9e681a8f 8bf8            mov     edi,eax
00007fff`9e681a91 85c0            test    eax,eax
00007fff`9e681a93 7923            jns     jscript!JsEval+0x158 (00007fff`9e681ab8)

我们可以在jscript断点COleScript :: Compile获取未编码的字符串示例调用calc.exe并将base64编码调用的解码版本的notepad.exe

0:000> bp jscript!COleScript::Compile "r $t1 = poi(rdx+0x10);r $t2 = poi($t1+0x8);du $t2;g";g
jscript!COleScript::Compile:
00007fff`9e715698 4053            push    rbx
0:000> g
0000019b`d23f6408  "var oShell = new ActiveXObject(""
0000019b`d23f6448  "Shell.Application");var commandt"
0000019b`d23f6488  "oRun = "calc.exe"; oShell.ShellE"
0000019b`d23f64c8  "xecute(commandtoRun,"","","","1""
0000019b`d23f6508  ");."
80070002 The system cannot find the file specified.
0000019b`d473a1b0  "var oShell = new ActiveXObject(""
0000019b`d473a1f0  "Shell.Application");var commandt"
0000019b`d473a230  "oRun = "notepad.exe"; oShell.She"
0000019b`d473a270  "llExecute(commandtoRun,"","","","
0000019b`d473a2b0  ""1");"
ntdll!NtTerminateProcess+0x14:
00007fff`c8e65924 c3              ret

结论

WinDBG是一个非常强大的工具不仅可以帮助您分析.NET文件还可以帮助您了解wscript.exe执行JavaScript。在许多情况下WinDBG可能会因为了解单个JavaScript文件的功能而过度使用。然而使用 WinDBG可以提供不同的功能概述并有助于分析复杂的JavaScript。

Python脚本从对象名称获取库

from _winreg import *
import sys

try:
  objectName = sys.argv[1]
except:
  sys.exit(1)

try:
  hReg = ConnectRegistry(None,HKEY_CLASSES_ROOT)
  hCLSIDKey = OpenKey(hReg, objectName+"CLSID")
  CLSID=QueryValue(hCLSIDKey, "")
  if CLSID:
    hKey = OpenKey(hReg, "CLSID\\"+CLSID)
    description = QueryValue(hKey, "")
    hKey = OpenKey(hReg, "CLSID\\"+CLSID+"\\InProcServer32")
    dll = QueryValueEx(hKey, "")[0]
    print "Object Name: "+objectName
    print "CLSID: "+CLSID
    print "Description: "+description
    print "dll: "+dll
  else:
    print "No CLSID"
except:
  print "Error"
  sys.exit(2)



原文发布时间为2017年8月17日
本文作者愣娃
本文来自云栖社区合作伙伴嘶吼了解相关信息可以关注嘶吼网站。
<think>我们使用WinDbg来检查ntoskrnl.exe是否损坏,主要可以通过以下步骤: 1. 加载正确的符号文件 2. 使用WinDbg的验证命令(如`!chkimg`)来检查内核映像的完整性 3. 分析可能的内存损坏或磁盘错误 具体步骤如下: ### 步骤1: 启动WinDbg并连接目标系统 由于ntoskrnl.exe是内核模块,我们需要在内核调试模式下使用WinDbg。可以通过以下方式之一: - 本地内核调试(需要启用调试模式并重启) - 双机调试(通过串口、USB或网络连接两台计算机) 这里以双机调试为例(假设已设置好调试连接)。 ### 步骤2: 加载符号 在WinDbg中,确保符号路径设置正确,以便加载ntoskrnl.exe的符号文件(.pdb)。在WinDbg命令窗口中输入: ```windbg .sympath srv*https://msdl.microsoft.com/download/symbols .reload /f ntoskrnl.exe ``` 如果符号加载成功,会显示类似信息: ``` DBGENG: ntoskrnl.exe - Partial symbol image load missing image info DBGHELP: nt - public symbols C:\Symbols\ntoskrnl.pdb\... ``` ### 步骤3: 检查ntoskrnl.exe的完整性 使用`!chkimg`命令来检查内核映像中的代码段是否被修改。这个命令会比较内存中的映像与符号文件中的原始代码,并报告差异。 输入命令: ```windbg !chkimg ntoskrnl ``` 或者指定模块的起始地址(如果知道的话): ```windbg !chkimg -lo 50 -d nt ``` 输出示例: ``` 0 errors : ntoskrnl.exe ``` 如果发现错误,则输出会显示错误的位置原始字节与当前字节的差异。 ### 步骤4: 分析错误 如果`!chkimg`报告有错误,可能意味着: - 磁盘上的ntoskrnl.exe文件损坏(需检查系统文件) - 内存中的内核代码被恶意软件修改(需进行安全扫描) - 硬件问题(如内存故障) 此时,可以进一步使用系统文件检查器(SFC)DISM工具来修复系统文件: 在目标系统的命令提示符(管理员)中运行: ```cmd sfc /scannow dism /online /cleanup-image /restorehealth ``` ### 步骤5: 使用`lm`命令查看模块信息 通过`lm`命令可以查看已加载的模块状态,确认ntoskrnl.exe的加载基址大小: ```windbg lmDvmntoskrnl ``` 检查输出中模块的加载状态,如果标记为`(deferred)`或`(pdb symbols not loaded)`,则可能存在问题。 ### 步骤6: 验证文件签名(可选) 在目标系统上,可以检查ntoskrnl.exe的数字签名: 1. 打开文件所在目录(通常为`C:\Windows\System32`) 2. 右键点击ntoskrnl.exe,选择“属性”>“数字签名” 3. 验证签名是否有效 或者使用PowerShell命令: ```powershell Get-AuthenticodeSignature -FilePath C:\Windows\System32\ntoskrnl.exe | Format-List ``` ### 注意事项 - 使用WinDbg需要一定的调试经验,特别是在内核模式下操作要谨慎。 - 如果`!chkimg`报告大量错误,可能是符号不匹配(例如,使用了错误版本的符号文件)。请确保符号文件与目标系统的Windows版本完全匹配。 通过以上步骤,我们可以初步判断ntoskrnl.exe是否损坏。如果确认损坏,建议通过安装系统更新或修复安装Windows来替换损坏的文件。 引用说明: [^1]: WinDbg Preview是经典WinDbg的现代替代品,具有更好的用户界面体验。 [^2]: 在WinDbg中设置断点等命令同样适用于检查模块加载。 [^3]: 如果系统文件损坏,可以尝试系统更新、修复或重置。 §§相关问题§§ 1. 如何设置双机调试环境来使用WinDbg? 2. WinDbg中还有哪些命令可以用于检查系统文件完整性? 3. 系统文件检查器(SFC)DISM工具的具体工作原理是什么?</think>要使用WinDbg检查`ntoskrnl.exe`是否损坏,请按照以下步骤操作: ### 检查步骤 1. **启动WinDbg Preview** - 从Microsoft Store安装[Windbg Preview](https://apps.microsoft.com/detail/9pgjgd53tn86)[^1] - 以管理员身份运行 2. **配置符号路径** 在命令窗口输入: ```windbg .sympath srv*https://msdl.microsoft.com/download/symbols .reload /f ``` ![符号加载成功示例](https://example.com/symbols-loaded.png) *确保加载`ntoskrnl.pdb`符号文件[^1]* 3. **验证文件完整性** ```windbg !chkimg ntoskrnl ``` - **正常输出**: `0 errors : ntoskrnl.exe` - **损坏迹象**: ```diff - 原始字节: 8b ff 55 8b ec + 内存字节: 8b ff cc cc cc (出现大量cc/00) ``` 4. **检查内存映射** ```windbg lmDvmntoskrnl ``` 关注关键字段: - `Loaded symbol image file`:是否显示完整路径 - `Image checksum`:是否匹配`0x<值>` - `ImageSize`:应为约`2.5MB`(视版本而定) 5. **验证函数入口点** ```windbg u nt!KiSystemStartup ``` 正常应显示有效的汇编指令(如`mov`/`call`),而非全`cc`或`??` ### 损坏判定标准 | 检查项 | 正常状态 | 损坏表现 | |-----------------------|------------------------------|------------------------------| | `!chkimg`结果 | 0错误 | 非零错误/字节不匹配 | | 内存字节 | 连续有效指令 | 大量`cc`(断点)或`00` | | 函数入口点 | 有效汇编代码 | `??`或无效指令 | | 模块状态(`lm`命令) | 显示完整签名校验 | "unloaded"/"no symbols" | ### 发现损坏后的操作 1. **运行系统修复工具** ```powershell sfc /scannow dism /online /cleanup-image /restorehealth ``` 2. **手动替换文件** - 从健康系统复制`C:\Windows\System32\ntoskrnl.exe` - 进入WinPE环境替换 - 使用安装媒体修复启动 3. **检查硬件问题** ```windbg !analyze -v ; 分析崩溃日志 !sysinfo machineid ; 检查硬件兼容性 ``` > ⚠️ 注意:如果`!chkimg`报告大量错误但系统稳定运行,可能是符号版本不匹配(需确保符号文件与系统版本完全一致)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值