Advanced Debugging
About AdvDbg Consult Train Services Products Tools Community Contact  
欢迎光临 高端调试 登录 | 注册 | FAQ
 
  ACPI调试
Linux内核调试
Windows内核调试
 
  调试战役
调试原理
新工具观察
 
  Linux
Windows Vista
Windows
 
  Linux驱动
WDF
WDM
 
  PCI Express
PCI/PCI-X
USB
无线通信协议
 
  64位CPU
ARM
IA-32
  CPU Info Center
 
  ACPI标准
系统认证
Desktop
服务器
 
  Embedded Linux
嵌入式开发工具
VxWorks
WinCE
嵌入式Windows
 
  格蠹调试套件(GDK)
  格蠹学院
  小朱书店
  老雷的微博
  《软件调试》
  《格蠹汇编》
  《软件调试(第二版)》
沪ICP备11027180号-1

Windows内核调试

帖子发起人: Windbger   发起时间: 2007-12-25 20:58 下午   回复: 8

Print Search
帖子排序:    
   2007-12-25, 20:58 下午
hsly110 离线,最后访问时间: 2007/12/25 20:55:49 Windbger

发帖数前500位
注册: 2007-12-25
发 贴: 2
我自己写了一个MBR,但是我想用VMWARE+WINDBG调试,可否可行?
Reply Quote
我自己写了一个MBR,但是我想用VMWARE+WINDBG调试,可否可行?

我听说 WMWARE+WINDBG 可以调试MBR 。是不是真的? 我也想尝试一下~

IP 地址: 已记录   报告
   2007-12-25, 22:29 下午
Raymond 离线,最后访问时间: 2020/7/3 3:40:25 格蠹老雷

发帖数前10位
注册: 2005-12-19
发 贴: 1,303
Re: 我自己写了一个MBR,但是我想用VMWARE+WINDBG调试,可否可行?
Reply Quote
我没有亲自做过,但是理论上是可行的。基本思想就是跟踪VMWARE的虚拟机的VCPU(虚拟CPU)执行MBR的过程。需要你对虚拟机的概念比较熟悉,以免搞不清是在执行虚拟机自己的代码,还是虚拟机内的客户代码。
调试MBR的更好方法当然是Bochs,建议你读一下王宇刚发的文章http://advdbg.org/blogs/advdbg_system/articles/441.aspx。
IP 地址: 已记录   报告
   2007-12-26, 01:00 上午
hsly110 离线,最后访问时间: 2007/12/25 20:55:49 Windbger

发帖数前500位
注册: 2007-12-25
发 贴: 2
Re: 我自己写了一个MBR,但是我想用VMWARE+WINDBG调试,可否可行?
Reply Quote
很高兴你的回复。
关于Bochs 的调试,我是比较熟悉的。因为自己开发了一个引导程序。
但是,现在我需要把引导程序跟WINDOWS结合。

所以必须 得 靠VMWARE 和 WINDBG 来调试。

但是,国内有少数人掌握了这些技术,比如 360安全卫士的内部开发者,还国外的一些开源开发者。

但是他们没有公布 更多的资料。

我只找到一点信息。 说是 通过 64号端口 来调试。

不过,你说的 [踪VMWARE的虚拟机的VCPU(虚拟CPU)执行MBR的过程] 这个信息非常重要。 能否提示 一下吗? 或者 给出一下 调试 VCPU 的相关资料
IP 地址: 已记录   报告
   2007-12-26, 23:24 下午
Raymond 离线,最后访问时间: 2020/7/3 3:40:25 格蠹老雷

发帖数前10位
注册: 2005-12-19
发 贴: 1,303
Re: 我自己写了一个MBR,但是我想用VMWARE+WINDBG调试,可否可行?
Reply Quote
不能理解为什么调试引导程序和Windows结合的问题就非得用VMWARE+WINDBG。如果使用WinDBG的内核调试功能,那么最早的调试时机也是在内核文件(NTOSKRNL.EXE)加载之后。如果使用WinDBG通过串口调试NTLDR的支持,那么也要在引导分区把控制权交给NTLDR之后。你现在要调的是MBR,那么离这两者还都差挺远。所以用WinDBG也只是把它当成一个普通的汇编语言调试器来用。
其实MBR之后是引导扇区的引导程序,使用DOS的Debug可以很好的调试这个代码。

IP 地址: 已记录   报告
   2008-04-10, 17:19 下午
WANGyu 离线,最后访问时间: 2012/9/10 3:34:00 王宇

发帖数前10位
男
注册: 2007-05-08
发 贴: 306
Re: 我自己写了一个MBR,但是我想用VMWARE+WINDBG调试,可否可行?
Reply Quote
1. 直接去问 MJ 他那个猥琐的逼近法是怎么实现的 ;)
2. 用 Bochs 调 + 自己写一些桩代码
3. 有条件就直接玩ICE

“所以必须得靠 VMWARE 和 WINDBG 来调试。” 理解是错的,关于双机调试的最早断点机会 Raymond 前辈已经回答你了。
IP 地址: 已记录   报告
   2008-04-24, 10:40 上午
WANGyu 离线,最后访问时间: 2012/9/10 3:34:00 王宇

发帖数前10位
男
注册: 2007-05-08
发 贴: 306
Re: 我自己写了一个MBR,但是我想用VMWARE+WINDBG调试,可否可行?
Reply Quote
详细地回答一下算了。

双机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 离线,最后访问时间: 2009/12/15 16:03:09 skyworth

发帖数前25位
注册: 2008-06-07
发 贴: 55
Re: 我自己写了一个MBR,但是我想用VMWARE+WINDBG调试,可否可行?
Reply Quote
我想这种情况下在编译的时候改变一下基址,就可以用turbo debugger很好的调试了。
IP 地址: 已记录   报告
   2008-06-26, 09:48 上午
WANGyu 离线,最后访问时间: 2012/9/10 3:34:00 王宇

发帖数前10位
男
注册: 2007-05-08
发 贴: 306
Re: 我自己写了一个MBR,但是我想用VMWARE+WINDBG调试,可否可行?
Reply Quote

在编译的时候改变一下基址或把它编译成 .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 离线,最后访问时间: 2009/12/15 16:03:09 skyworth

发帖数前25位
注册: 2008-06-07
发 贴: 55
Re: 我自己写了一个MBR,但是我想用VMWARE+WINDBG调试,可否可行?
Reply Quote
呵呵,开眼界了
IP 地址: 已记录   报告
高端调试 » 软件调试 » Windows内核调试 » Re: 我自己写了一个MBR,但是我想用VMWARE+WINDBG调试,可否可行?

 
Legal Notice Privacy Statement Corporate Governance Corporate Governance
(C)2004-2020 ADVDBG.ORG All Rights Reserved.