|
|
|
|
|
|
|
Windows内核调试
帖子发起人: Windbger 发起时间: 2007-12-25 20:58 下午 回复: 8
|
帖子排序:
|
|
|
|
2007-12-25, 20:58 下午
|
Windbger
注册: 2007-12-25
发 贴: 2
|
我自己写了一个MBR,但是我想用VMWARE+WINDBG调试,可否可行?
|
|
|
|
我自己写了一个MBR,但是我想用VMWARE+WINDBG调试,可否可行?
我听说 WMWARE+WINDBG 可以调试MBR 。是不是真的? 我也想尝试一下~
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
2007-12-25, 22:29 下午
|
格蠹老雷
注册: 2005-12-19
发 贴: 1,303
|
Re: 我自己写了一个MBR,但是我想用VMWARE+WINDBG调试,可否可行?
|
|
|
|
我没有亲自做过,但是理论上是可行的。基本思想就是跟踪VMWARE的虚拟机的VCPU(虚拟CPU)执行MBR的过程。需要你对虚拟机的概念比较熟悉,以免搞不清是在执行虚拟机自己的代码,还是虚拟机内的客户代码。
调试MBR的更好方法当然是Bochs,建议你读一下王宇刚发的文章http://advdbg.org/blogs/advdbg_system/articles/441.aspx。
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
2007-12-26, 01:00 上午
|
Windbger
注册: 2007-12-25
发 贴: 2
|
Re: 我自己写了一个MBR,但是我想用VMWARE+WINDBG调试,可否可行?
|
|
|
|
很高兴你的回复。
关于Bochs 的调试,我是比较熟悉的。因为自己开发了一个引导程序。
但是,现在我需要把引导程序跟WINDOWS结合。
所以必须 得 靠VMWARE 和 WINDBG 来调试。
但是,国内有少数人掌握了这些技术,比如 360安全卫士的内部开发者,还国外的一些开源开发者。
但是他们没有公布 更多的资料。
我只找到一点信息。 说是 通过 64号端口 来调试。
不过,你说的 [踪VMWARE的虚拟机的VCPU(虚拟CPU)执行MBR的过程] 这个信息非常重要。 能否提示 一下吗? 或者 给出一下 调试 VCPU 的相关资料
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
2007-12-26, 23:24 下午
|
格蠹老雷
注册: 2005-12-19
发 贴: 1,303
|
Re: 我自己写了一个MBR,但是我想用VMWARE+WINDBG调试,可否可行?
|
|
|
|
不能理解为什么调试引导程序和Windows结合的问题就非得用VMWARE+WINDBG。如果使用WinDBG的内核调试功能,那么最早的调试时机也是在内核文件(NTOSKRNL.EXE)加载之后。如果使用WinDBG通过串口调试NTLDR的支持,那么也要在引导分区把控制权交给NTLDR之后。你现在要调的是MBR,那么离这两者还都差挺远。所以用WinDBG也只是把它当成一个普通的汇编语言调试器来用。
其实MBR之后是引导扇区的引导程序,使用DOS的Debug可以很好的调试这个代码。
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
2008-04-10, 17:19 下午
|
王宇
注册: 2007-05-08
发 贴: 306
|
Re: 我自己写了一个MBR,但是我想用VMWARE+WINDBG调试,可否可行?
|
|
|
|
1. 直接去问 MJ 他那个猥琐的逼近法是怎么实现的 ;) 2. 用 Bochs 调 + 自己写一些桩代码 3. 有条件就直接玩ICE
“所以必须得靠 VMWARE 和 WINDBG 来调试。” 理解是错的,关于双机调试的最早断点机会 Raymond 前辈已经回答你了。
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
2008-04-24, 10:40 上午
|
王宇
注册: 2007-05-08
发 贴: 306
|
Re: 我自己写了一个MBR,但是我想用VMWARE+WINDBG调试,可否可行?
|
|
|
|
详细地回答一下算了。
双机Windbg调试第一次获得断点的机会不足以调试Boot过程,因为相对于启动而言,OS级的调试还是太晚了。下面是调用序列,显然 nt!KiSystemStartup 是 Ntldr 完成之后 Jmp 执行的入口:
kd> kv
ChildEBP RetAddr Args to Child
80549c5c 80683baa 00000001 80552920 00000000 nt!RtlpBreakWithStatusInstruction (FPO: [1,0,0])
80549de8 80690d48 00000000 80087000 8003fc00 nt!ExpInitializeExecutive+0x350 (FPO: [Non-Fpo])
80549e3c 8068e99b 80552b80 80552920 8054a100 nt!KiInitializeKernel+0x3b2 (FPO: [Non-Fpo])
00000000 00000000 00000000 00000000 00000000 nt!KiSystemStartup+0x2bf
此时 _LOADER_PARAMETER_BLOCK 等早已组织好了。
换成 MS 的代码是这样的:
VOID
ExpInitializeExecutive(
IN ULONG Number,
IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
/*++
Routine Description:
This routine is called from the kernel initialization routine during
bootstrap to initialize the executive and all of its subcomponents.
Each subcomponent is potentially called twice to perform Phase 0, and
then Phase 1 initialization. During Phase 0 initialization, the only
activity that may be performed is the initialization of subcomponent
specific data. Phase 0 initialization is performed in the context of
the kernel start up routine with interrupts disabled. During Phase 1
initialization, the system is fully operational and subcomponents may
do any initialization that is necessary.
Arguments:
Number - Supplies the processor number currently initializing.
LoaderBlock - Supplies a pointer to a loader parameter block.
Return Value:
None.
--*/
{
PFN_COUNT PagesToBurn;
PCHAR Options;
PCHAR MemoryOption;
NTSTATUS Status;
PKLDR_DATA_TABLE_ENTRY DataTableEntry;
PLIST_ENTRY NextEntry;
ANSI_STRING AnsiString;
STRING NameString;
CHAR Buffer[ 256 ];
BOOLEAN BufferSizeOk;
ULONG ImageCount;
ULONG i;
ULONG_PTR ResourceIdPath[3];
PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry;
PMESSAGE_RESOURCE_DATA MessageData;
PLIST_ENTRY NextMd;
PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
if (!ExpIsLoaderValid(LoaderBlock)) {
KeBugCheckEx(MISMATCHED_HAL,
3,
LoaderBlock->Extension->Size,
LoaderBlock->Extension->MajorVersion,
LoaderBlock->Extension->MinorVersion
);
}
//
// Initialize PRCB pool lookaside pointers.
//
#if !defined(_AMD64_)
ExInitPoolLookasidePointers();
#endif
if (Number == 0) {
extern BOOLEAN ExpInTextModeSetup;
//
// Determine whether this is textmode setup and whether this is a
// remote boot client.
//
ExpInTextModeSetup = FALSE;
IoRemoteBootClient = FALSE;
if (LoaderBlock->SetupLoaderBlock != NULL) {
if ((LoaderBlock->SetupLoaderBlock->Flags & SETUPBLK_FLAGS_IS_TEXTMODE) != 0) {
ExpInTextModeSetup = TRUE;
}
if ((LoaderBlock->SetupLoaderBlock->Flags & SETUPBLK_FLAGS_IS_REMOTE_BOOT) != 0) {
IoRemoteBootClient = TRUE;
ASSERT( _memicmp( LoaderBlock->ArcBootDeviceName, "net(0)", 6 ) == 0 );
}
}
#if defined(REMOTE_BOOT)
SharedUserData->SystemFlags = 0;
if (IoRemoteBootClient) {
SharedUserData->SystemFlags |= SYSTEM_FLAG_REMOTE_BOOT_CLIENT;
}
#endif // defined(REMOTE_BOOT)
//
// Indicate that we are in phase 0.
//
InitializationPhase = 0L;
Options = LoaderBlock->LoadOptions;
if (Options != NULL) {
//
// If in BBT mode, remove the requested amount of memory from the
// loader block and use it for BBT purposes instead.
//
_strupr(Options);
MemoryOption = strstr(Options, "PERFMEM");
if (MemoryOption != NULL) {
MemoryOption = strstr (MemoryOption,"=");
if (MemoryOption != NULL) {
PagesToBurn = (PFN_COUNT) atol (MemoryOption + 1);
//
// Convert MB to pages.
//
PagesToBurn *= ((1024 * 1024) / PAGE_SIZE);
if (PagesToBurn != 0) {
PERFINFO_INIT_TRACEFLAGS(Options, MemoryOption);
BBTPagesToReserve = ExBurnMemory (LoaderBlock,
PagesToBurn,
LoaderBBTMemory,
&BBTMemoryDescriptor);
}
}
}
//
// Burn memory - consume the amount of memory
// specified in the OS Load Options. This is used
// for testing reduced memory configurations.
//
MemoryOption = strstr(Options, "BURNMEMORY");
if (MemoryOption != NULL) {
MemoryOption = strstr(MemoryOption,"=");
if (MemoryOption != NULL ) {
PagesToBurn = (PFN_COUNT) atol (MemoryOption + 1);
//
// Convert MB to pages.
//
PagesToBurn *= ((1024 * 1024) / PAGE_SIZE);
if (PagesToBurn != 0) {
ExBurnMemory (LoaderBlock,
PagesToBurn,
LoaderBad,
NULL);
}
}
}
}
//
// Initialize the translation tables using the loader
// loaded tables.
//
InitNlsTableBase = LoaderBlock->NlsData->AnsiCodePageData;
InitAnsiCodePageDataOffset = 0;
InitOemCodePageDataOffset = (ULONG)((PUCHAR)LoaderBlock->NlsData->OemCodePageData - (PUCHAR)LoaderBlock->NlsData->AnsiCodePageData);
InitUnicodeCaseTableDataOffset = (ULONG)((PUCHAR)LoaderBlock->NlsData->UnicodeCaseTableData - (PUCHAR)LoaderBlock->NlsData->AnsiCodePageData);
RtlInitNlsTables(
(PVOID)((PUCHAR)InitNlsTableBase+InitAnsiCodePageDataOffset),
(PVOID)((PUCHAR)InitNlsTableBase+InitOemCodePageDataOffset),
(PVOID)((PUCHAR)InitNlsTableBase+InitUnicodeCaseTableDataOffset),
&InitTableInfo
);
RtlResetRtlTranslations(&InitTableInfo);
//
// Initialize the Hardware Architecture Layer (HAL).
//
if (HalInitSystem(InitializationPhase, LoaderBlock) == FALSE) {
KeBugCheck(HAL_INITIALIZATION_FAILED);
}
#if defined(_APIC_TPR_)
HalpIRQLToTPR = LoaderBlock->Extension->HalpIRQLToTPR;
HalpVectorToIRQL = LoaderBlock->Extension->HalpVectorToIRQL;
#endif
//
// Enable interrupts now that the HAL has initialized.
//
#if defined(_X86_)
_enable();
#endif
//
// Set the interrupt time forward so the Win32 tick count will wrap
// within one hour to make rollover errors show up in fewer than 49.7
// days.
//
#if DBG
KeAdjustInterruptTime((LONGLONG)(MAXULONG - (60 * 60 * 1000)) * 10 * 1000);
#endif
SharedUserData->CryptoExponent = 0;
#if DBG
NtGlobalFlag |= FLG_ENABLE_CLOSE_EXCEPTIONS |
FLG_ENABLE_KDEBUG_SYMBOL_LOAD;
#endif
Status = RtlFormatBuffer2( Buffer,
sizeof(Buffer),
"C:%s",
LoaderBlock->NtBootPathName,
0
);
if (! NT_SUCCESS(Status)) {
KeBugCheck(SESSION3_INITIALIZATION_FAILED);
}
RtlInitString( &AnsiString, Buffer );
Buffer[ --AnsiString.Length ] = '\0';
NtSystemRoot.Buffer = SharedUserData->NtSystemRoot;
NtSystemRoot.MaximumLength = sizeof( SharedUserData->NtSystemRoot );
NtSystemRoot.Length = 0;
Status = RtlAnsiStringToUnicodeString( &NtSystemRoot,
&AnsiString,
FALSE
);
if (!NT_SUCCESS( Status )) {
KeBugCheck(SESSION3_INITIALIZATION_FAILED);
}
//
// Find the address of BugCheck message block resource and put it
// in KiBugCodeMessages.
//
// WARNING: This code assumes that the KLDR_DATA_TABLE_ENTRY for
// ntoskrnl.exe is always the first in the loaded module list.
//
DataTableEntry = CONTAINING_RECORD(LoaderBlock->LoadOrderListHead.Flink,
KLDR_DATA_TABLE_ENTRY,
InLoadOrderLinks);
ResourceIdPath[0] = 11;
ResourceIdPath[1] = 1;
ResourceIdPath[2] = 0;
Status = LdrFindResource_U (DataTableEntry->DllBase,
ResourceIdPath,
3,
(VOID *) &ResourceDataEntry);
if (NT_SUCCESS(Status)) {
Status = LdrAccessResource (DataTableEntry->DllBase,
ResourceDataEntry,
&MessageData,
NULL);
if (NT_SUCCESS(Status)) {
KiBugCodeMessages = MessageData;
}
}
#if !defined(NT_UP)
//
// Verify that the kernel and HAL images are suitable for MP systems.
//
// N.B. Loading of kernel and HAL symbols now occurs in kdinit.
//
ImageCount = 0;
NextEntry = LoaderBlock->LoadOrderListHead.Flink;
while ((NextEntry != &LoaderBlock->LoadOrderListHead) && (ImageCount DllBase) ) {
KeBugCheckEx(UP_DRIVER_ON_MP_SYSTEM,
(ULONG_PTR)DataTableEntry->DllBase,
0,
0,
0);
}
NextEntry = NextEntry->Flink;
}
#endif // !defined(NT_UP)
CmpInitSystemVersion(0, LoaderBlock);
//
// Initialize the ExResource package.
//
if (!ExInitSystem()) {
KeBugCheck(PHASE0_INITIALIZATION_FAILED);
}
//
// Get multinode configuration (if any).
//
KeNumaInitialize();
//
// Initialize memory management and the memory allocation pools.
//
if (MmInitSystem (0, LoaderBlock) == FALSE) {
KeBugCheck(PHASE0_INITIALIZATION_FAILED);
}
//
// Scan the loaded module list and load the driver image symbols.
//
ImageCount = 0;
NextEntry = LoaderBlock->LoadOrderListHead.Flink;
while (NextEntry != &LoaderBlock->LoadOrderListHead) {
BufferSizeOk = TRUE;
if (ImageCount >= 2) {
ULONG Count;
WCHAR *Filename;
ULONG Length;
//
// Get the address of the data table entry for the next component.
//
DataTableEntry = CONTAINING_RECORD(NextEntry,
KLDR_DATA_TABLE_ENTRY,
InLoadOrderLinks);
//
// Load the symbols via the kernel debugger
// for the next component.
//
if (DataTableEntry->FullDllName.Buffer[0] == L'\\') {
//
// Correct fullname already available
//
Filename = DataTableEntry->FullDllName.Buffer;
Length = DataTableEntry->FullDllName.Length / sizeof(WCHAR);
if (sizeof(Buffer) BaseDllName.Length / sizeof(WCHAR)
+ sizeof(ANSI_NULL)) {
//
// ignore the driver entry, it must have been corrupt.
//
BufferSizeOk = FALSE;
} else {
Status = RtlFormatBuffer2 (Buffer,
sizeof(Buffer),
"%ws\\System32\\Drivers\\%wZ",
&SharedUserData->NtSystemRoot[2],
&DataTableEntry->BaseDllName);
if (! NT_SUCCESS(Status)) {
KeBugCheck(PHASE0_INITIALIZATION_FAILED);
}
}
}
if (BufferSizeOk) {
RtlInitString (&NameString, Buffer );
DbgLoadImageSymbols (&NameString,
DataTableEntry->DllBase,
(ULONG)-1);
#if !defined(NT_UP)
if (!MmVerifyImageIsOkForMpUse(DataTableEntry->DllBase)) {
KeBugCheckEx(UP_DRIVER_ON_MP_SYSTEM,(ULONG_PTR)DataTableEntry->DllBase,0,0,0);
}
#endif // NT_UP
}
}
ImageCount += 1;
NextEntry = NextEntry->Flink;
}
//
// If break after symbol load is specified, then break into the
// debugger.
//
if (KdBreakAfterSymbolLoad != FALSE) {
DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
}
......................
这句 DbgBreakPointWithStatus() 才OS级第一次中断到调试器,别说MBR了,内核的代码都跑了一堆了...
所以,
要用“猥琐的方法逼近”... ^_^
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
2008-06-22, 09:24 上午
|
skyworth
注册: 2008-06-07
发 贴: 55
|
Re: 我自己写了一个MBR,但是我想用VMWARE+WINDBG调试,可否可行?
|
|
|
|
我想这种情况下在编译的时候改变一下基址,就可以用turbo debugger很好的调试了。
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
2008-06-26, 09:48 上午
|
王宇
注册: 2007-05-08
发 贴: 306
|
Re: 我自己写了一个MBR,但是我想用VMWARE+WINDBG调试,可否可行?
|
|
|
|
在编译的时候改变一下基址或把它编译成 .com 文件格式再用 TC 调试肯定没问题。
但是楼主说是要:“但是,现在我需要把引导程序跟WINDOWS结合。”,这种做法和他的要求不符。
只有“虚拟机级别”的调试才能满足需要,“OS级别的调试”太晚,而“编译器级别的调试”仅仅是程序本身除错。
除了OS级的调试入口在我上面的回帖以外,Win 还支持 Ntldr 的调试和跟踪。后者显然比前者跟早,方法是 调试版的 ntldr / osloader 以及他们的符号。
我现在的 osloader 符号不完全正确,下初始化断点之后,windbg 可以识别模块名,而不能识别函数名。但是,对我来说这不是致命的,没有符号并不等于不能工作。 ; )
*** WARNING: Unable to verify timestamp for osloader.exe *** ERROR: Module load completed but symbols could not be loaded for osloader.exe osloader+0x1b438: 0041b438 cc int 3
这就是这个 Loader 的断点,位于 osloader+0x1b438 。如果符号正确的话,应该显示为: osloader!DbgBreakPoint。
请参见下面的描述: When the debugger breaks in, you will see a message that the symbol checksum cannot be verified. Ignore this message! If you want to verify that your symbols are correct, do a stack trace and make sure the first line of the stack trace says osloader!DbgBreakPoint.
反汇编信息: kd> u 0041b438 l30 osloader+0x1b438: 0041b438 cc int 3 0041b439 c20400 ret 4 0041b43c 55 push ebp 0041b43d 8bec mov ebp,esp 0041b43f 33c0 xor eax,eax 0041b441 8a4508 mov al,byte ptr [ebp+8] 0041b444 25ff000000 and eax,0FFh 0041b449 6685c0 test ax,ax 0041b44c 742c je osloader+0x1b47a (0041b47a) 0041b44e 663d0100 cmp ax,1 0041b452 7426 je osloader+0x1b47a (0041b47a) 0041b454 a8f0 test al,0F0h 0041b456 7407 je osloader+0x1b45f (0041b45f) 0041b458 b85f0200c0 mov eax,0C000025Fh 0041b45d eb20 jmp osloader+0x1b47f (0041b47f) 0041b45f ff751c push dword ptr [ebp+1Ch] 0041b462 0fb7c0 movzx eax,ax 0041b465 ff7518 push dword ptr [ebp+18h] 0041b468 ff7514 push dword ptr [ebp+14h] 0041b46b ff7510 push dword ptr [ebp+10h] 0041b46e ff750c push dword ptr [ebp+0Ch] 0041b471 ff14853c384300 call dword ptr osloader+0x3383c (0043383c)[eax*4] 0041b478 eb05 jmp osloader+0x1b47f (0041b47f) 0041b47a b80d0000c0 mov eax,0C000000Dh 0041b47f 5d pop ebp 0041b480 c21800 ret 18h 0041b483 55 push ebp 0041b484 8bec mov ebp,esp 0041b486 33c0 xor eax,eax 0041b488 8a4508 mov al,byte ptr [ebp+8] 0041b48b 25ff000000 and eax,0FFh 0041b490 6685c0 test ax,ax 0041b493 7429 je osloader+0x1b4be (0041b4be) 0041b495 663d0100 cmp ax,1 0041b499 7423 je osloader+0x1b4be (0041b4be) 0041b49b a8f0 test al,0F0h 0041b49d 7407 je osloader+0x1b4a6 (0041b4a6) 0041b49f b85f0200c0 mov eax,0C000025Fh 0041b4a4 eb1d jmp osloader+0x1b4c3 (0041b4c3) 0041b4a6 ff7518 push dword ptr [ebp+18h] 0041b4a9 0fb7c0 movzx eax,ax 0041b4ac ff7514 push dword ptr [ebp+14h] 0041b4af ff7510 push dword ptr [ebp+10h] 0041b4b2 ff750c push dword ptr [ebp+0Ch] 0041b4b5 ff14857c384300 call dword ptr osloader+0x3387c (0043387c)[eax*4] 0041b4bc eb05 jmp osloader+0x1b4c3 (0041b4c3) 0041b4be b80d0000c0 mov eax,0C000000Dh 0041b4c3 5d pop ebp
最后,楼主要干的事情,我原来干过的,截些图给你看看 (我用的 freeldr + Ntoskrnl):
NTOSKRNL.EXE not found 的原因是我用的 软盘镜像 来模拟启动区和磁盘本身, NTOSKRNL.EXE 的大小超过 1.44MB, 所以得用更大的磁盘镜像才能继续, 那样的话我可能还需要重写引导扇区的代码, 现在我的引导扇区代码只支持 FAT-12 文件格式, 懒得改了, 过几天再说~ ^_^
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
2008-06-26, 22:06 下午
|
skyworth
注册: 2008-06-07
发 贴: 55
|
Re: 我自己写了一个MBR,但是我想用VMWARE+WINDBG调试,可否可行?
|
|
|
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
高端调试 » 软件调试 » Windows内核调试 » Re: 我自己写了一个MBR,但是我想用VMWARE+WINDBG调试,可否可行?
|
|
|
|
|
|