发信人: flier (小海 [渴望并不存在的完美]), 信区: MSDN
标 题: Detours x64 [Draft]
发信站: 水木社区 (Fri Aug 3 01:01:07 2007), 站内
该死的路径依赖,为了折腾另外一个问题,不得不先把这个搞定 :S
Detours我就不介绍了,MSR放出的2.1 Express版本不支持64位
而据某人发邮件问,要10000刀才给授权,基本也不用想了 -_-b
于是乎在此基础上修修补补,基本能在x64下跑起来
因为还有些bug,暂时不放完整版本出来,大概说说流程
API Hook 基本已经是大白菜级技术,无非就是找到函数入口点
替换前面几个字节为jmp,重定向到一个跳板,完成工作再跳回去
详细的流程请参考detours的代码,下面捡x64下不一样的说
首先是在DetourAttachEx时找到原始函数和Hook函数的真实代码入口点
可能需要跳过import表,或者调试用间接跳转指令啥的,
detours.cpp里detour_skip_jmp函数就是干这个的,
不过在x64下需要做一些调整,因为某些指令的数据长度跟x86不同
这块代码我基本照抄mhook的实现,比detours增加了嵌套检查
inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals)
{
if (pbCode == NULL) {
return NULL;
}
if (ppGlobals != NULL) {
*ppGlobals = NULL;
}
if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32]
// Looks like an import alias jump, then get the code it points to.
// on x64 we have a 32-bit offset...
PBYTE pbTarget = *(PBYTE*)(pbCode + 6 + *(INT32 *)&pbCode[2]);
if (detour_is_imported(pbCode, pbTarget)) {
PBYTE pbNew = *(PBYTE *)pbTarget;
DETOUR_TRACE(("%p->%p: skipped over import table./n", pbCode, pbNew));
return pbNew;
}
return detour_skip_jmp(pbTarget, ppGlobals);
}
else if (pbCode[0] == 0xe9) { // jmp + rel32, Near jump with the target
/*
SEH64!ILT+15(?CallThatFunctionYAHXZ):
00000000`00401014 e957000000 jmp SEH64!CallThatFunction (000000
00`00401070)
SEH64!CallThatFunction [d:/study/win64/seh64/seh64.cpp @ 11]:
00000000`00401070 4057 push rdi
00000000`00401072 4883ec40 sub rsp,40h
00000000`00401076 488bfc mov rdi,rsp
*/
PBYTE pbNew = pbCode + 5 + *(INT32 *)&pbCode[1];
return detour_skip_jmp(pbNew, ppGlobals);
}
else if (pbCode[0] == 0xeb) { // jmp +imm8
// These just started appearing with CL13.
PBYTE pbNew = pbCode + 2 + *(CHAR *)&pbCode[1];
return detour_skip_jmp(pbNew, ppGlobals);
}
return pbCode;
}
知道入口后,detours会调用DetourCopyInstructionEx复制入口处代码
其根据字节可能代表的指令,把相关信息放到s_rceCopyTable表中
x64下需要修改的是从0x40到0x4f这几个入口,x64指令集中用他们
作为REX前缀,详细说明参见AMD architecture programmer manual volume 3
1.2.7 REX Prefixes 小节中有详细讨论,这儿全部当成单字节前缀即可
#ifdef DETOURS_X64 // For Rex Prefix
{ 0x40, ENTRY_CopyBytesPrefix }, // REX Prefixes
{ 0x41, ENTRY_CopyBytesPrefix }, // REX Prefixes
{ 0x42, ENTRY_CopyBytesPrefix }, // REX Prefixes
{ 0x43, ENTRY_CopyBytesPrefix }, // REX Prefixes
{ 0x44, ENTRY_CopyBytesPrefix }, // REX Prefixes
{ 0x45, ENTRY_CopyBytesPrefix }, // REX Prefixes
{ 0x46, ENTRY_CopyBytesPrefix }, // REX Prefixes
{ 0x47, ENTRY_CopyBytesPrefix }, // REX Prefixes
{ 0x48, ENTRY_CopyBytesPrefix }, // REX Prefixes
{ 0x49, ENTRY_CopyBytesPrefix }, // REX Prefixes
{ 0x4A, ENTRY_CopyBytesPrefix }, // REX Prefixes
{ 0x4B, ENTRY_CopyBytesPrefix }, // REX Prefixes
{ 0x4C, ENTRY_CopyBytesPrefix }, // REX Prefixes
{ 0x4D, ENTRY_CopyBytesPrefix }, // REX Prefixes
{ 0x4E, ENTRY_CopyBytesPrefix }, // REX Prefixes
{ 0x4F, ENTRY_CopyBytesPrefix }, // REX Prefixes
#else
而对FF开始的far indirect jmp/call 指令,x64也跟x86不同
PBYTE CDetourDis::CopyFF(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
{ // CALL /2
// CALL /3
// INC /0
// JMP /4
// JMP /5
// PUSH /6
(void)pEntry;
if (0x15 == pbSrc[1] || 0x25 == pbSrc[1]) { // CALL [], JMP []
#ifdef DETOURS_X64
DWORD dwOffset = *((PDWORD)&pbSrc[2]);
*m_ppbTarget = (PBYTE)*((PDWORD_PTR)(pbSrc + 6 + dwOffset));
#else
PBYTE *ppbTarget = *(PBYTE**)&pbSrc[2];
*m_ppbTarget = *ppbTarget;
#endif
}
else if (0x10 == (0x38 & pbSrc[1]) || // CALL /2 --> reg(bits 543) of Mo
dR/M == 010
0x18 == (0x38 & pbSrc[1]) || // CALL /3 --> reg(bits 543) of Mo
dR/M == 011
0x20 == (0x38 & pbSrc[1]) || // JMP /4 --> reg(bits 543) of Mod
R/M == 100
0x28 == (0x38 & pbSrc[1]) // JMP /5 --> reg(bits 543) of Mod
R/M == 101
) {
*m_ppbTarget = (PBYTE)DETOUR_INSTRUCTION_TARGET_DYNAMIC;
}
const COPYENTRY ce = { 0xff, ENTRY_CopyBytes2Mod };
return (this->*ce.pfCopy)(&ce, pbDst, pbSrc);
}
拷贝了原始指令到跳板后,需要在后面增加跳回剩余指令的jmp
x86下面detours直接用detour_gen_jmp_immediate函数生成指令
但在x64下面需要修改,因为x64下面指针是64位的,
如果目标地址在当前地址前后2G范围内,可以用32位偏移跳转
否则必须把地址放到内存中,然后在jmp指令指定保存地址的位置
detours在通过detour_alloc_trampoline函数分配跳板内存时
会尽量尝试把内存分配在目标函数2G范围内,避免长跳转指令
这样可以确保目标函数大于5字节(near jmp) 时都能工作
但这样一来就无法确保跳板跟hook函数的位置在2G内,
所以x64下面必须处理这些情况,同理照抄mhook代码如下
inline PBYTE detour_gen_jmp(PBYTE pbCode, PBYTE pbJumpTo)
{
PBYTE pbJumpFrom = pbCode + 5;
SIZE_T cbDiff = pbJumpFrom > pbJumpTo ? pbJumpFrom - pbJumpTo : pbJumpTo -
pbJumpFrom;
if (cbDiff <= 0x7fff0000) {
*pbCode++ = 0xe9;
*((PDWORD)pbCode) = (DWORD)(DWORD_PTR)(pbJumpTo - pbJumpFrom);
pbCode += sizeof(DWORD);
} else {
*pbCode++ = 0xff;
*pbCode++ = 0x25;
// on x64 we write the relative address of the same location
*((PDWORD)pbCode) = (DWORD)0;
pbCode += sizeof(DWORD);
*((PDWORD_PTR)pbCode) = (DWORD_PTR)(pbJumpTo);
pbCode += sizeof(DWORD_PTR);
}
return pbCode;
}
除此之外,还有一些异常情况的处理,例如暂停线程时,
其RIP刚好在跳板或者目标函数入口处,理论上可以使用
与x86相同的机制,不过暂时没法构造环境测试
#ifdef DETOURS_X64
#define DETOURS_EIP Rip
#define DETOURS_EIP_TYPE DWORD64
#endif // DETOURS_X64
最后还有一些跟细节的处理,例如对ModRm下RIP的处理
回头加上再一起放出完整可用的代码吧
Reference
1. Microsoft Research Detours Package
http://research.microsoft.com/research/downloads/Details/d36340fb-4d3c-4ddd-bf5b-1db25d03713d/Details.aspx
2. Mhook, an API hooking library, V2.0
http://codefromthe70s.org/mhook2.asp
3. AMD64 Architecture Programmer’s Manual Volume 3: General-Purpose and System Instructions
4. Everything You Need To Know To Start Programming 64-Bit Windows Systems, Matt Pietrek
http://msdn.microsoft.com/msdnmag/issues/06/05/x64/default.aspx?print=true&loc=null
. 生命的意义在于 // ____/ //_ / //_/ http://flier_lu.blogcn.com .
. 希望 / / /___/_/// / //_/__ __ _ _★ .
. 工作 / / ____// / / // / /'__`/ //`'_/ .
. 爱你的人 / / /___/ / / /___/ / /// __// / / // .
. 和你爱的人 / /___/ / /_____/ /__/ /____/ / /_/ .
. …… //___/ //_____///__///____/ //_/
[email protected] .
※ 修改:·flier 于 Aug 3 01:01:35 修改本文·[FROM: 221.226.232.*]
※ 来源:·水木社区 newsmth.net·[FROM: 221.226.232.*]
发信人: FreeWizard ( ), 信区: MSDN
标 题: Re: Detours x64 [Draft]
发信站: 水木社区 (Fri Aug 3 01:02:58 2007), 站内
orz
先re再看
【 在 flier (小海 [渴望并不存在的完美]) 的大作中提到: 】
: 该死的路径依赖,为了折腾另外一个问题,不得不先把这个搞定 :S
: Detours我就不介绍了,MSR放出的2.1 Express版本不支持64位
: 而据某人发邮件问,要10000刀才给授权,基本也不用想了 -_-b
: ...................
--
※ 来源:·水木社区 newsmth.net·[FROM: 221.221.18.159]
发信人: flier (小海 [渴望并不存在的完美]), 信区: MSDN
标 题: Re: Detours x64 [Draft]
发信站: 水木社区 (Fri Aug 3 01:11:16 2007), 站内
编译了一下 detours 那个 dtest 例子,代码完全不受影响,设置一下库就行
这个是vs2005编译后的调试版本,可以用windbg看看,呵呵,xp pro x64 下测试通过
【 在 flier (小海 [渴望并不存在的完美]) 的大作中提到: 】
: 该死的路径依赖,为了折腾另外一个问题,不得不先把这个搞定 :S
: Detours我就不介绍了,MSR放出的2.1 Express版本不支持64位
: 而据某人发邮件问,要10000刀才给授权,基本也不用想了 -_-b
: ...................
--
. 生命的意义在于 // ____/ //_ / //_/ http://flier_lu.blogcn.com .
. 希望 / / /___/_/// / //_/__ __ _ _★ .
. 工作 / / ____// / / // / /'__`/ //`'_/ .
. 爱你的人 / / /___/ / / /___/ / /// __// / / // .
. 和你爱的人 / /___/ / /_____/ /__/ /____/ / /_/ .
. …… //___/ //_____///__///____/ //_/
[email protected] .
※ 来源:·水木社区 http://newsmth.net·[FROM: 221.226.232.*]
附件: Debug64.rar (237KB)
附件: pdb.rar (634KB)
发信人: peach (换台机器挂站), 信区: MSDN
标 题: Re: Detours x64 [Draft]
发信站: 水木社区 (Fri Aug 3 08:32:21 2007), 站内
最近也折腾了一些这方面的东西,但不是64位的
有些想法,正好拿出来
API HOOK 还可以用另外一种方法,虽然也会用到 detours 相关的技术,不过性能上有不少折扣
这种方法的核心思想就是使用 SEH,在需要 HOOK 的 API 入口处,改成一个 user break point 即可,这时候只要接管 SEH 处理函数即可,在 SEH 处理函数中,你可以修改 CONTEXT::Eip 以及其他寄存器来达到改变程序的流程的目的。
这时候有两个问题,
1、API入口的第一条指令。
a) 绝对跳转之类的指令(jmp, call)。将 user break point 移至跳转到的地址处。
b) 条件跳转。这种情况似乎很少见
c) 其他指令。移走,在其他地方执行。
2、如何接管 SEH 处理函数。
Detours 中有 DetourFirstChanceExceptionFilter,可以让你在第一时间处理所发生的异常。
如果需要 HOOK 的 API 不是很多,user break point 都不用加,用硬件调试寄存器就可以完成了。
【 在 flier (小海 [渴望并不存在的完美]) 的大作中提到: 】
: 标 题: Detours x64 [Draft]
: 发信站: 水木社区 (Fri Aug 3 01:01:07 2007), 站内
:
: 该死的路径依赖,为了折腾另外一个问题,不得不先把这个搞定 :S
:
: Detours我就不介绍了,MSR放出的2.1 Express版本不支持64位
: 而据某人发邮件问,要10000刀才给授权,基本也不用想了 -_-b
:
: 于是乎在此基础上修修补补,基本能在x64下跑起来
: 因为还有些bug,暂时不放完整版本出来,大概说说流程
:
: API Hook 基本已经是大白菜级技术,无非就是找到函数入口点
: 替换前面几个字节为jmp,重定向到一个跳板,完成工作再跳回去
: 详细的流程请参考detours的代码,下面捡x64下不一样的说
:
: 首先是在DetourAttachEx时找到原始函数和Hook函数的真实代码入口点
: 可能需要跳过import表,或者调试用间接跳转指令啥的,
: detours.cpp里detour_skip_jmp函数就是干这个的,
: 不过在x64下需要做一些调整,因为某些指令的数据长度跟x86不同
: 这块代码我基本照抄mhook的实现,比detours增加了嵌套检查
:
:
:
: inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals)
:
: {
:
: if (pbCode == NULL) {
:
: return NULL;
:
: }
:
: if (ppGlobals != NULL) {
:
: *ppGlobals = NULL;
:
: }
:
: if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32]
:
: // Looks like an import alias jump, then get the code it points to.
:
: // on x64 we have a 32-bit offset...
:
: PBYTE pbTarget = *(PBYTE*)(pbCode + 6 + *(INT32 *)&pbCode[2]);
:
: if (detour_is_imported(pbCode, pbTarget)) {
:
: PBYTE pbNew = *(PBYTE *)pbTarget;
:
: DETOUR_TRACE(("%p->%p: skipped over import table./n", pbCode, pbNew));
:
:
: return pbNew;
:
: }
:
: return detour_skip_jmp(pbTarget, ppGlobals);
:
: }
:
: else if (pbCode[0] == 0xe9) { // jmp + rel32, Near jump with the target
:
: /*
:
: SEH64!ILT+15(?CallThatFunctionYAHXZ):
:
: 00000000`00401014 e957000000 jmp SEH64!CallThatFunction (000000
: 00`00401070)
:
: SEH64!CallThatFunction [d:/study/win64/seh64/seh64.cpp @ 11]:
:
: 00000000`00401070 4057 push rdi
:
: 00000000`00401072 4883ec40 sub rsp,40h
:
: 00000000`00401076 488bfc mov rdi,rsp
:
: */
:
: PBYTE pbNew = pbCode + 5 + *(INT32 *)&pbCode[1];
:
: return detour_skip_jmp(pbNew, ppGlobals);
:
: }
:
: else if (pbCode[0] == 0xeb) { // jmp +imm8
:
: // These just started appearing with CL13.
:
: PBYTE pbNew = pbCode + 2 + *(CHAR *)&pbCode[1];
:
: return detour_skip_jmp(pbNew, ppGlobals);
:
: }
:
: return pbCode;
:
: }
:
: 知道入口后,detours会调用DetourCopyInstructionEx复制入口处代码
: 其根据字节可能代表的指令,把相关信息放到s_rceCopyTable表中
: x64下需要修改的是从0x40到0x4f这几个入口,x64指令集中用他们
: 作为REX前缀,详细说明参见AMD architecture programmer manual volume 3
: 1.2.7 REX Prefixes 小节中有详细讨论,这儿全部当成单字节前缀即可
:
: #ifdef DETOURS_X64 // For Rex Prefix
: { 0x40, ENTRY_CopyBytesPrefix }, // REX Prefixes
: { 0x41, ENTRY_CopyBytesPrefix }, // REX Prefixes
: { 0x42, ENTRY_CopyBytesPrefix }, // REX Prefixes
:
: { 0x43, ENTRY_CopyBytesPrefix }, // REX Prefixes
: { 0x44, ENTRY_CopyBytesPrefix }, // REX Prefixes
: { 0x45, ENTRY_CopyBytesPrefix }, // REX Prefixes
: { 0x46, ENTRY_CopyBytesPrefix }, // REX Prefixes
: { 0x47, ENTRY_CopyBytesPrefix }, // REX Prefixes
: { 0x48, ENTRY_CopyBytesPrefix }, // REX Prefixes
: { 0x49, ENTRY_CopyBytesPrefix }, // REX Prefixes
: { 0x4A, ENTRY_CopyBytesPrefix }, // REX Prefixes
: { 0x4B, ENTRY_CopyBytesPrefix }, // REX Prefixes
: { 0x4C, ENTRY_CopyBytesPrefix }, // REX Prefixes
: { 0x4D, ENTRY_CopyBytesPrefix }, // REX Prefixes
: { 0x4E, ENTRY_CopyBytesPrefix }, // REX Prefixes
: { 0x4F, ENTRY_CopyBytesPrefix }, // REX Prefixes
: #else
:
: 而对FF开始的far indirect jmp/call 指令,x64也跟x86不同
:
: PBYTE CDetourDis::CopyFF(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
:
: { // CALL /2
:
: // CALL /3
:
: // INC /0
:
: // JMP /4
:
: // JMP /5
:
: // PUSH /6
:
: (void)pEntry;
:
: if (0x15 == pbSrc[1] || 0x25 == pbSrc[1]) { // CALL [], JMP []
:
: #ifdef DETOURS_X64
:
: DWORD dwOffset = *((PDWORD)&pbSrc[2]);
:
: *m_ppbTarget = (PBYTE)*((PDWORD_PTR)(pbSrc + 6 + dwOffset));
:
: #else
:
: PBYTE *ppbTarget = *(PBYTE**)&pbSrc[2];
:
: *m_ppbTarget = *ppbTarget;
:
: #endif
:
: }
:
: else if (0x10 == (0x38 & pbSrc[1]) || // CALL /2 --> reg(bits 543) of Mo
: dR/M == 010
:
: 0x18 == (0x38 & pbSrc[1]) || // CALL /3 --> reg(bits 543) of Mo
: dR/M == 011
:
: 0x20 == (0x38 & pbSrc[1]) || // JMP /4 --> reg(bits 543) of Mod
: R/M == 100
:
: 0x28 == (0x38 & pbSrc[1]) // JMP /5 --> reg(bits 543) of Mod
: R/M == 101
:
: ) {
:
: *m_ppbTarget = (PBYTE)DETOUR_INSTRUCTION_TARGET_DYNAMIC;
:
: }
:
: const COPYENTRY ce = { 0xff, ENTRY_CopyBytes2Mod };
:
: return (this->*ce.pfCopy)(&ce, pbDst, pbSrc);
:
: }
:
: 拷贝了原始指令到跳板后,需要在后面增加跳回剩余指令的jmp
: x86下面detours直接用detour_gen_jmp_immediate函数生成指令
: 但在x64下面需要修改,因为x64下面指针是64位的,
: 如果目标地址在当前地址前后2G范围内,可以用32位偏移跳转
: 否则必须把地址放到内存中,然后在jmp指令指定保存地址的位置
:
: detours在通过detour_alloc_trampoline函数分配跳板内存时
: 会尽量尝试把内存分配在目标函数2G范围内,避免长跳转指令
: 这样可以确保目标函数大于5字节(near jmp) 时都能工作
: 但这样一来就无法确保跳板跟hook函数的位置在2G内,
: 所以x64下面必须处理这些情况,同理照抄mhook代码如下
:
: inline PBYTE detour_gen_jmp(PBYTE pbCode, PBYTE pbJumpTo)
:
: {
:
: PBYTE pbJumpFrom = pbCode + 5;
:
: SIZE_T cbDiff = pbJumpFrom > pbJumpTo ? pbJumpFrom - pbJumpTo : pbJumpTo -
: pbJumpFrom;
:
: if (cbDiff <= 0x7fff0000) {
:
: *pbCode++ = 0xe9;
:
: *((PDWORD)pbCode) = (DWORD)(DWORD_PTR)(pbJumpTo - pbJumpFrom);
:
: pbCode += sizeof(DWORD);
:
: } else {
:
: *pbCode++ = 0xff;
:
: *pbCode++ = 0x25;
:
: // on x64 we write the relative address of the same location
:
: *((PDWORD)pbCode) = (DWORD)0;
:
: pbCode += sizeof(DWORD);
:
:
:
: *((PDWORD_PTR)pbCode) = (DWORD_PTR)(pbJumpTo);
:
: pbCode += sizeof(DWORD_PTR);
:
: }
:
: return pbCode;
:
: }
:
: 除此之外,还有一些异常情况的处理,例如暂停线程时,
: 其RIP刚好在跳板或者目标函数入口处,理论上可以使用
: 与x86相同的机制,不过暂时没法构造环境测试
:
: #ifdef DETOURS_X64
:
: #define DETOURS_EIP Rip
: #define DETOURS_EIP_TYPE DWORD64
:
: #endif // DETOURS_X64
:
: 最后还有一些跟细节的处理,例如对ModRm下RIP的处理
: 回头加上再一起放出完整可用的代码吧
:
: Reference
:
: 1. Microsoft Research Detours Package
: http://research.microsoft.com/research/downloads/Details/d36340fb-4d3c-4ddd-bf5b-1db25d03713d/Details.aspx
:
: 2. Mhook, an API hooking library, V2.0
: http://codefromthe70s.org/mhook2.asp
:
: 3. AMD64 Architecture Programmer’s Manual Volume 3: General-Purpose and System Instructions
:
: 4. Everything You Need To Know To Start Programming 64-Bit Windows Systems, Matt Pietrek
: http://msdn.microsoft.com/msdnmag/issues/06/05/x64/default.aspx?print=true&loc=null
: . 生命的意义在于 // ____/ //_ / //_/ http://flier_lu.blogcn.com .
: . 希望 / / /___/_/// / //_/__ __ _ _★ .
: . 工作 / / ____// / / // / /'__`/ //`'_/ .
: . 爱你的人 / / /___/ / / /___/ / /// __// / / // .
: . 和你爱的人 / /___/ / /_____/ /__/ /____/ / /_/ .
: . …… //___/ //_____///__///____/ //_/[email protected] .
:
:
: ※ 修改:·flier 于 Aug 3 01:01:35 修改本文·[FROM: 221.226.232.*]
: ※ 来源:·水木社区 newsmth.net·[FROM: 221.226.232.*]
--
※ 来源:·水木社区 newsmth.net·[FROM: 166.111.8.*]
发信人: bbinn (明天的明天), 信区: MSDN
标 题: Re: Detours x64 [Draft]
发信站: 水木社区 (Fri Aug 3 08:55:39 2007), 站内
牛
【 在 flier (小海 [渴望并不存在的完美]) 的大作中提到: 】
: 标 题: Detours x64 [Draft]
: 发信站: 水木社区 (Fri Aug 3 01:01:07 2007), 站内
:
: 该死的路径依赖,为了折腾另外一个问题,不得不先把这个搞定 :S
:
: Detours我就不介绍了,MSR放出的2.1 Express版本不支持64位
: 而据某人发邮件问,要10000刀才给授权,基本也不用想了 -_-b
:
: 于是乎在此基础上修修补补,基本能在x64下跑起来
: 因为还有些bug,暂时不放完整版本出来,大概说说流程
:
: API Hook 基本已经是大白菜级技术,无非就是找到函数入口点
: 替换前面几个字节为jmp,重定向到一个跳板,完成工作再跳回去
: 详细的流程请参考detours的代码,下面捡x64下不一样的说
:
: 首先是在DetourAttachEx时找到原始函数和Hook函数的真实代码入口点
: 可能需要跳过import表,或者调试用间接跳转指令啥的,
: detours.cpp里detour_skip_jmp函数就是干这个的,
: 不过在x64下需要做一些调整,因为某些指令的数据长度跟x86不同
: 这块代码我基本照抄mhook的实现,比detours增加了嵌套检查
:
:
:
: inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals)
:
: {
:
: if (pbCode == NULL) {
:
: return NULL;
:
: }
:
: if (ppGlobals != NULL) {
:
: *ppGlobals = NULL;
:
: }
:
: if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32]
:
: // Looks like an import alias jump, then get the code it points to.
:
: // on x64 we have a 32-bit offset...
:
: PBYTE pbTarget = *(PBYTE*)(pbCode + 6 + *(INT32 *)&pbCode[2]);
:
: if (detour_is_imported(pbCode, pbTarget)) {
:
: PBYTE pbNew = *(PBYTE *)pbTarget;
:
: DETOUR_TRACE(("%p->%p: skipped over import table./n", pbCode, pbNew));
:
:
: return pbNew;
:
: }
:
: return detour_skip_jmp(pbTarget, ppGlobals);
:
: }
:
: else if (pbCode[0] == 0xe9) { // jmp + rel32, Near jump with the target
:
: /*
:
: SEH64!ILT+15(?CallThatFunctionYAHXZ):
:
: 00000000`00401014 e957000000 jmp SEH64!CallThatFunction (000000
: 00`00401070)
:
: SEH64!CallThatFunction [d:/study/win64/seh64/seh64.cpp @ 11]:
:
: 00000000`00401070 4057 push rdi
:
: 00000000`00401072 4883ec40 sub rsp,40h
:
: 00000000`00401076 488bfc mov rdi,rsp
:
: */
:
: PBYTE pbNew = pbCode + 5 + *(INT32 *)&pbCode[1];
:
: return detour_skip_jmp(pbNew, ppGlobals);
:
: }
:
: else if (pbCode[0] == 0xeb) { // jmp +imm8
:
: // These just started appearing with CL13.
:
: PBYTE pbNew = pbCode + 2 + *(CHAR *)&pbCode[1];
:
: return detour_skip_jmp(pbNew, ppGlobals);
:
: }
:
: return pbCode;
:
: }
:
: 知道入口后,detours会调用DetourCopyInstructionEx复制入口处代码
: 其根据字节可能代表的指令,把相关信息放到s_rceCopyTable表中
: x64下需要修改的是从0x40到0x4f这几个入口,x64指令集中用他们
: 作为REX前缀,详细说明参见AMD architecture programmer manual volume 3
: 1.2.7 REX Prefixes 小节中有详细讨论,这儿全部当成单字节前缀即可
:
: #ifdef DETOURS_X64 // For Rex Prefix
: { 0x40, ENTRY_CopyBytesPrefix }, // REX Prefixes
: { 0x41, ENTRY_CopyBytesPrefix }, // REX Prefixes
: { 0x42, ENTRY_CopyBytesPrefix }, // REX Prefixes
:
: { 0x43, ENTRY_CopyBytesPrefix }, // REX Prefixes
: { 0x44, ENTRY_CopyBytesPrefix }, // REX Prefixes
: { 0x45, ENTRY_CopyBytesPrefix }, // REX Prefixes
: { 0x46, ENTRY_CopyBytesPrefix }, // REX Prefixes
: { 0x47, ENTRY_CopyBytesPrefix }, // REX Prefixes
: { 0x48, ENTRY_CopyBytesPrefix }, // REX Prefixes
: { 0x49, ENTRY_CopyBytesPrefix }, // REX Prefixes
: { 0x4A, ENTRY_CopyBytesPrefix }, // REX Prefixes
: { 0x4B, ENTRY_CopyBytesPrefix }, // REX Prefixes
: { 0x4C, ENTRY_CopyBytesPrefix }, // REX Prefixes
: { 0x4D, ENTRY_CopyBytesPrefix }, // REX Prefixes
: { 0x4E, ENTRY_CopyBytesPrefix }, // REX Prefixes
: { 0x4F, ENTRY_CopyBytesPrefix }, // REX Prefixes
: #else
:
: 而对FF开始的far indirect jmp/call 指令,x64也跟x86不同
:
: PBYTE CDetourDis::CopyFF(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
:
: { // CALL /2
:
: // CALL /3
:
: // INC /0
:
: // JMP /4
:
: // JMP /5
:
: // PUSH /6
:
: (void)pEntry;
:
: if (0x15 == pbSrc[1] || 0x25 == pbSrc[1]) { // CALL [], JMP []
:
: #ifdef DETOURS_X64
:
: DWORD dwOffset = *((PDWORD)&pbSrc[2]);
:
: *m_ppbTarget = (PBYTE)*((PDWORD_PTR)(pbSrc + 6 + dwOffset));
:
: #else
:
: PBYTE *ppbTarget = *(PBYTE**)&pbSrc[2];
:
: *m_ppbTarget = *ppbTarget;
:
: #endif
:
: }
:
: else if (0x10 == (0x38 & pbSrc[1]) || // CALL /2 --> reg(bits 543) of Mo
: dR/M == 010
:
: 0x18 == (0x38 & pbSrc[1]) || // CALL /3 --> reg(bits 543) of Mo
: dR/M == 011
:
: 0x20 == (0x38 & pbSrc[1]) || // JMP /4 --> reg(bits 543) of Mod
: R/M == 100
:
: 0x28 == (0x38 & pbSrc[1]) // JMP /5 --> reg(bits 543) of Mod
: R/M == 101
:
: ) {
:
: *m_ppbTarget = (PBYTE)DETOUR_INSTRUCTION_TARGET_DYNAMIC;
:
: }
:
: const COPYENTRY ce = { 0xff, ENTRY_CopyBytes2Mod };
:
: return (this->*ce.pfCopy)(&ce, pbDst, pbSrc);
:
: }
:
: 拷贝了原始指令到跳板后,需要在后面增加跳回剩余指令的jmp
: x86下面detours直接用detour_gen_jmp_immediate函数生成指令
: 但在x64下面需要修改,因为x64下面指针是64位的,
: 如果目标地址在当前地址前后2G范围内,可以用32位偏移跳转
: 否则必须把地址放到内存中,然后在jmp指令指定保存地址的位置
:
: detours在通过detour_alloc_trampoline函数分配跳板内存时
: 会尽量尝试把内存分配在目标函数2G范围内,避免长跳转指令
: 这样可以确保目标函数大于5字节(near jmp) 时都能工作
: 但这样一来就无法确保跳板跟hook函数的位置在2G内,
: 所以x64下面必须处理这些情况,同理照抄mhook代码如下
:
: inline PBYTE detour_gen_jmp(PBYTE pbCode, PBYTE pbJumpTo)
:
: {
:
: PBYTE pbJumpFrom = pbCode + 5;
:
: SIZE_T cbDiff = pbJumpFrom > pbJumpTo ? pbJumpFrom - pbJumpTo : pbJumpTo -
: pbJumpFrom;
:
: if (cbDiff <= 0x7fff0000) {
:
: *pbCode++ = 0xe9;
:
: *((PDWORD)pbCode) = (DWORD)(DWORD_PTR)(pbJumpTo - pbJumpFrom);
:
: pbCode += sizeof(DWORD);
:
: } else {
:
: *pbCode++ = 0xff;
:
: *pbCode++ = 0x25;
:
: // on x64 we write the relative address of the same location
:
: *((PDWORD)pbCode) = (DWORD)0;
:
: pbCode += sizeof(DWORD);
:
:
:
: *((PDWORD_PTR)pbCode) = (DWORD_PTR)(pbJumpTo);
:
: pbCode += sizeof(DWORD_PTR);
:
: }
:
: return pbCode;
:
: }
:
: 除此之外,还有一些异常情况的处理,例如暂停线程时,
: 其RIP刚好在跳板或者目标函数入口处,理论上可以使用
: 与x86相同的机制,不过暂时没法构造环境测试
:
: #ifdef DETOURS_X64
:
: #define DETOURS_EIP Rip
: #define DETOURS_EIP_TYPE DWORD64
:
: #endif // DETOURS_X64
:
: 最后还有一些跟细节的处理,例如对ModRm下RIP的处理
: 回头加上再一起放出完整可用的代码吧
:
: Reference
:
: 1. Microsoft Research Detours Package
: http://research.microsoft.com/research/downloads/Details/d36340fb-4d3c-4ddd-bf5b-1db25d03713d/Details.aspx
:
: 2. Mhook, an API hooking library, V2.0
: http://codefromthe70s.org/mhook2.asp
:
: 3. AMD64 Architecture Programmer’s Manual Volume 3: General-Purpose and System Instructions
:
: 4. Everything You Need To Know To Start Programming 64-Bit Windows Systems, Matt Pietrek
: http://msdn.microsoft.com/msdnmag/issues/06/05/x64/default.aspx?print=true&loc=null
: . 生命的意义在于 // ____/ //_ / //_/ http://flier_lu.blogcn.com .
: . 希望 / / /___/_/// / //_/__ __ _ _★ .
: . 工作 / / ____// / / // / /'__`/ //`'_/ .
: . 爱你的人 / / /___/ / / /___/ / /// __// / / // .
: . 和你爱的人 / /___/ / /_____/ /__/ /____/ / /_/ .
: . …… //___/ //_____///__///____/ //_/[email protected] .
:
:
: ※ 修改:·flier 于 Aug 3 01:01:35 修改本文·[FROM: 221.226.232.*]
: ※ 来源:·水木社区 newsmth.net·[FROM: 221.226.232.*]
--
- 不谈金钱,不谈妇女,不谈琐事
※ 来源:·水木社区 newsmth.net·[FROM: 219.232.52.*]
发信人: bbinn (明天的明天), 信区: MSDN
标 题: Re: Detours x64 [Draft]
发信站: 水木社区 (Fri Aug 3 08:58:20 2007), 站内
太赞了,我现在就在折腾这个。
不过OLE嵌入的时候你这招就不管用了,debug break会先被csrss.exe捕获到,
然后就直接认为嵌入失败,然后进程就suspend了。
【 在 peach (换台机器挂站) 的大作中提到: 】
: 标 题: Re: Detours x64 [Draft]
: 发信站: 水木社区 (Fri Aug 3 08:32:21 2007), 站内
:
: 最近也折腾了一些这方面的东西,但不是64位的
:
: 有些想法,正好拿出来
:
: API HOOK 还可以用另外一种方法,虽然也会用到 detours 相关的技术,不过性能上有不少折扣
:
: 这种方法的核心思想就是使用 SEH,在需要 HOOK 的 API 入口处,改成一个 user break point 即可,这时候只要接管 SEH 处理函数即可,在 SEH 处理函数中,你可以修改 CONTEXT::Eip 以及其他寄存器来达到改变程序的流程的目的。
:
: 这时候有两个问题,
: 1、API入口的第一条指令。
: a) 绝对跳转之类的指令(jmp, call)。将 user break point 移至跳转到的地址处。
: b) 条件跳转。这种情况似乎很少见
: c) 其他指令。移走,在其他地方执行。
:
: 2、如何接管 SEH 处理函数。
: Detours 中有 DetourFirstChanceExceptionFilter,可以让你在第一时间处理所发生的异常。
:
: 如果需要 HOOK 的 API 不是很多,user break point 都不用加,用硬件调试寄存器就可以完成了。
:
:
: 【 在 flier (小海 [渴望并不存在的完美]) 的大作中提到: 】
: : 标 题: Detours x64 [Draft]
: : 发信站: 水木社区 (Fri Aug 3 01:01:07 2007), 站内
: :
: : 该死的路径依赖,为了折腾另外一个问题,不得不先把这个搞定 :S
: :
: : Detours我就不介绍了,MSR放出的2.1 Express版本不支持64位
: : 而据某人发邮件问,要10000刀才给授权,基本也不用想了 -_-b
: :
: : 于是乎在此基础上修修补补,基本能在x64下跑起来
: : 因为还有些bug,暂时不放完整版本出来,大概说说流程
: :
: : API Hook 基本已经是大白菜级技术,无非就是找到函数入口点
: : 替换前面几个字节为jmp,重定向到一个跳板,完成工作再跳回去
: : 详细的流程请参考detours的代码,下面捡x64下不一样的说
: :
: : 首先是在DetourAttachEx时找到原始函数和Hook函数的真实代码入口点
: : 可能需要跳过import表,或者调试用间接跳转指令啥的,
: : detours.cpp里detour_skip_jmp函数就是干这个的,
: : 不过在x64下需要做一些调整,因为某些指令的数据长度跟x86不同
: : 这块代码我基本照抄mhook的实现,比detours增加了嵌套检查
: :
: :
: :
: : inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals)
: :
: : {
: :
: : if (pbCode == NULL) {
: :
: : return NULL;
: :
: : }
: :
: : if (ppGlobals != NULL) {
: :
: : *ppGlobals = NULL;
: :
: : }
: :
: : if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32]
: :
: : // Looks like an import alias jump, then get the code it points to.
: :
: : // on x64 we have a 32-bit offset...
: :
: : PBYTE pbTarget = *(PBYTE*)(pbCode + 6 + *(INT32 *)&pbCode[2]);
: :
: : if (detour_is_imported(pbCode, pbTarget)) {
: :
: : PBYTE pbNew = *(PBYTE *)pbTarget;
: :
: : DETOUR_TRACE(("%p->%p: skipped over import table./n", pbCode, pbNew));
: :
: :
: : return pbNew;
: :
: : }
: :
: : return detour_skip_jmp(pbTarget, ppGlobals);
: :
: : }
: :
: : else if (pbCode[0] == 0xe9) { // jmp + rel32, Near jump with the target
: :
: : /*
: :
: : SEH64!ILT+15(?CallThatFunctionYAHXZ):
: :
: : 00000000`00401014 e957000000 jmp SEH64!CallThatFunction (000000
: : 00`00401070)
: :
: : SEH64!CallThatFunction [d:/study/win64/seh64/seh64.cpp @ 11]:
: :
: : 00000000`00401070 4057 push rdi
: :
: : 00000000`00401072 4883ec40 sub rsp,40h
: :
: : 00000000`00401076 488bfc mov rdi,rsp
: :
: : */
: :
: : PBYTE pbNew = pbCode + 5 + *(INT32 *)&pbCode[1];
: :
: : return detour_skip_jmp(pbNew, ppGlobals);
: :
: : }
: :
: : else if (pbCode[0] == 0xeb) { // jmp +imm8
: :
: : // These just started appearing with CL13.
: :
: : PBYTE pbNew = pbCode + 2 + *(CHAR *)&pbCode[1];
: :
: : return detour_skip_jmp(pbNew, ppGlobals);
: :
: : }
: :
: : return pbCode;
: :
: : }
: :
: : 知道入口后,detours会调用DetourCopyInstructionEx复制入口处代码
: : 其根据字节可能代表的指令,把相关信息放到s_rceCopyTable表中
: : x64下需要修改的是从0x40到0x4f这几个入口,x64指令集中用他们
: : 作为REX前缀,详细说明参见AMD architecture programmer manual volume 3
: : 1.2.7 REX Prefixes 小节中有详细讨论,这儿全部当成单字节前缀即可
: :
: : #ifdef DETOURS_X64 // For Rex Prefix
: : { 0x40, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : { 0x41, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : { 0x42, ENTRY_CopyBytesPrefix }, // REX Prefixes
: :
: : { 0x43, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : { 0x44, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : { 0x45, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : { 0x46, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : { 0x47, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : { 0x48, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : { 0x49, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : { 0x4A, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : { 0x4B, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : { 0x4C, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : { 0x4D, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : { 0x4E, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : { 0x4F, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : #else
: :
: : 而对FF开始的far indirect jmp/call 指令,x64也跟x86不同
: :
: : PBYTE CDetourDis::CopyFF(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
: :
: : { // CALL /2
: :
: : // CALL /3
: :
: : // INC /0
: :
: : // JMP /4
: :
: : // JMP /5
: :
: : // PUSH /6
: :
: : (void)pEntry;
: :
: : if (0x15 == pbSrc[1] || 0x25 == pbSrc[1]) { // CALL [], JMP []
: :
: : #ifdef DETOURS_X64
: :
: : DWORD dwOffset = *((PDWORD)&pbSrc[2]);
: :
: : *m_ppbTarget = (PBYTE)*((PDWORD_PTR)(pbSrc + 6 + dwOffset));
: :
: : #else
: :
: : PBYTE *ppbTarget = *(PBYTE**)&pbSrc[2];
: :
: : *m_ppbTarget = *ppbTarget;
: :
: : #endif
: :
: : }
: :
: : else if (0x10 == (0x38 & pbSrc[1]) || // CALL /2 --> reg(bits 543) of Mo
: : dR/M == 010
: :
: : 0x18 == (0x38 & pbSrc[1]) || // CALL /3 --> reg(bits 543) of Mo
: : dR/M == 011
: :
: : 0x20 == (0x38 & pbSrc[1]) || // JMP /4 --> reg(bits 543) of Mod
: : R/M == 100
: :
: : 0x28 == (0x38 & pbSrc[1]) // JMP /5 --> reg(bits 543) of Mod
: : R/M == 101
: :
: : ) {
: :
: : *m_ppbTarget = (PBYTE)DETOUR_INSTRUCTION_TARGET_DYNAMIC;
: :
: : }
: :
: : const COPYENTRY ce = { 0xff, ENTRY_CopyBytes2Mod };
: :
: : return (this->*ce.pfCopy)(&ce, pbDst, pbSrc);
: :
: : }
: :
: : 拷贝了原始指令到跳板后,需要在后面增加跳回剩余指令的jmp
: : x86下面detours直接用detour_gen_jmp_immediate函数生成指令
: : 但在x64下面需要修改,因为x64下面指针是64位的,
: : 如果目标地址在当前地址前后2G范围内,可以用32位偏移跳转
: : 否则必须把地址放到内存中,然后在jmp指令指定保存地址的位置
: :
: : detours在通过detour_alloc_trampoline函数分配跳板内存时
: : 会尽量尝试把内存分配在目标函数2G范围内,避免长跳转指令
: : 这样可以确保目标函数大于5字节(near jmp) 时都能工作
: : 但这样一来就无法确保跳板跟hook函数的位置在2G内,
: : 所以x64下面必须处理这些情况,同理照抄mhook代码如下
: :
: : inline PBYTE detour_gen_jmp(PBYTE pbCode, PBYTE pbJumpTo)
: :
: : {
: :
: : PBYTE pbJumpFrom = pbCode + 5;
: :
: : SIZE_T cbDiff = pbJumpFrom > pbJumpTo ? pbJumpFrom - pbJumpTo : pbJumpTo -
: : pbJumpFrom;
: :
: : if (cbDiff <= 0x7fff0000) {
: :
: : *pbCode++ = 0xe9;
: :
: : *((PDWORD)pbCode) = (DWORD)(DWORD_PTR)(pbJumpTo - pbJumpFrom);
: :
: : pbCode += sizeof(DWORD);
: :
: : } else {
: :
: : *pbCode++ = 0xff;
: :
: : *pbCode++ = 0x25;
: :
: : // on x64 we write the relative address of the same location
: :
: : *((PDWORD)pbCode) = (DWORD)0;
: :
: : pbCode += sizeof(DWORD);
: :
: :
: :
: : *((PDWORD_PTR)pbCode) = (DWORD_PTR)(pbJumpTo);
: :
: : pbCode += sizeof(DWORD_PTR);
: :
: : }
: :
: : return pbCode;
: :
: : }
: :
: : 除此之外,还有一些异常情况的处理,例如暂停线程时,
: : 其RIP刚好在跳板或者目标函数入口处,理论上可以使用
: : 与x86相同的机制,不过暂时没法构造环境测试
: :
: : #ifdef DETOURS_X64
: :
: : #define DETOURS_EIP Rip
: : #define DETOURS_EIP_TYPE DWORD64
: :
: : #endif // DETOURS_X64
: :
: : 最后还有一些跟细节的处理,例如对ModRm下RIP的处理
: : 回头加上再一起放出完整可用的代码吧
: :
: : Reference
: :
: : 1. Microsoft Research Detours Package
: : http://research.microsoft.com/research/downloads/Details/d36340fb-4d3c-4ddd-bf5b-1db25d03713d/Details.aspx
: :
: : 2. Mhook, an API hooking library, V2.0
: : http://codefromthe70s.org/mhook2.asp
: :
: : 3. AMD64 Architecture Programmer’s Manual Volume 3: General-Purpose and System Instructions
: :
: : 4. Everything You Need To Know To Start Programming 64-Bit Windows Systems, Matt Pietrek
: : http://msdn.microsoft.com/msdnmag/issues/06/05/x64/default.aspx?print=true&loc=null
: : . 生命的意义在于 // ____/ //_ / //_/ http://flier_lu.blogcn.com .
: : . 希望 / / /___/_/// / //_/__ __ _ _★ .
: : . 工作 / / ____// / / // / /'__`/ //`'_/ .
: : . 爱你的人 / / /___/ / / /___/ / /// __// / / // .
: : . 和你爱的人 / /___/ / /_____/ /__/ /____/ / /_/ .
: : . …… //___/ //_____///__///____/ //_/[email protected] .
: :
: :
: : ※ 修改:·flier 于 Aug 3 01:01:35 修改本文·[FROM: 221.226.232.*]
: : ※ 来源:·水木社区 newsmth.net·[FROM: 221.226.232.*]
:
:
: --
:
: ※ 来源:·水木社区 newsmth.net·[FROM: 166.111.8.*]
--
- 不谈金钱,不谈妇女,不谈琐事
※ 来源:·水木社区 newsmth.net·[FROM: 219.232.52.*]
发信人: bbinn (明天的明天), 信区: MSDN
标 题: Re: Detours x64 [Draft]
发信站: 水木社区 (Fri Aug 3 09:03:59 2007), 站内
可能这样要好一点,就是把user break point改成 divide by 0,
就不会有别的机制抢着去处理这个异常了,就是字节多一点。
【 在 peach (换台机器挂站) 的大作中提到: 】
: 标 题: Re: Detours x64 [Draft]
: 发信站: 水木社区 (Fri Aug 3 08:32:21 2007), 站内
:
: 最近也折腾了一些这方面的东西,但不是64位的
:
: 有些想法,正好拿出来
:
: API HOOK 还可以用另外一种方法,虽然也会用到 detours 相关的技术,不过性能上有不少折扣
:
: 这种方法的核心思想就是使用 SEH,在需要 HOOK 的 API 入口处,改成一个 user break point 即可,这时候只要接管 SEH 处理函数即可,在 SEH 处理函数中,你可以修改 CONTEXT::Eip 以及其他寄存器来达到改变程序的流程的目的。
:
: 这时候有两个问题,
: 1、API入口的第一条指令。
: a) 绝对跳转之类的指令(jmp, call)。将 user break point 移至跳转到的地址处。
: b) 条件跳转。这种情况似乎很少见
: c) 其他指令。移走,在其他地方执行。
:
: 2、如何接管 SEH 处理函数。
: Detours 中有 DetourFirstChanceExceptionFilter,可以让你在第一时间处理所发生的异常。
:
: 如果需要 HOOK 的 API 不是很多,user break point 都不用加,用硬件调试寄存器就可以完成了。
:
:
: 【 在 flier (小海 [渴望并不存在的完美]) 的大作中提到: 】
: : 标 题: Detours x64 [Draft]
: : 发信站: 水木社区 (Fri Aug 3 01:01:07 2007), 站内
: :
: : 该死的路径依赖,为了折腾另外一个问题,不得不先把这个搞定 :S
: :
: : Detours我就不介绍了,MSR放出的2.1 Express版本不支持64位
: : 而据某人发邮件问,要10000刀才给授权,基本也不用想了 -_-b
: :
: : 于是乎在此基础上修修补补,基本能在x64下跑起来
: : 因为还有些bug,暂时不放完整版本出来,大概说说流程
: :
: : API Hook 基本已经是大白菜级技术,无非就是找到函数入口点
: : 替换前面几个字节为jmp,重定向到一个跳板,完成工作再跳回去
: : 详细的流程请参考detours的代码,下面捡x64下不一样的说
: :
: : 首先是在DetourAttachEx时找到原始函数和Hook函数的真实代码入口点
: : 可能需要跳过import表,或者调试用间接跳转指令啥的,
: : detours.cpp里detour_skip_jmp函数就是干这个的,
: : 不过在x64下需要做一些调整,因为某些指令的数据长度跟x86不同
: : 这块代码我基本照抄mhook的实现,比detours增加了嵌套检查
: :
: :
: :
: : inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals)
: :
: : {
: :
: : if (pbCode == NULL) {
: :
: : return NULL;
: :
: : }
: :
: : if (ppGlobals != NULL) {
: :
: : *ppGlobals = NULL;
: :
: : }
: :
: : if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32]
: :
: : // Looks like an import alias jump, then get the code it points to.
: :
: : // on x64 we have a 32-bit offset...
: :
: : PBYTE pbTarget = *(PBYTE*)(pbCode + 6 + *(INT32 *)&pbCode[2]);
: :
: : if (detour_is_imported(pbCode, pbTarget)) {
: :
: : PBYTE pbNew = *(PBYTE *)pbTarget;
: :
: : DETOUR_TRACE(("%p->%p: skipped over import table./n", pbCode, pbNew));
: :
: :
: : return pbNew;
: :
: : }
: :
: : return detour_skip_jmp(pbTarget, ppGlobals);
: :
: : }
: :
: : else if (pbCode[0] == 0xe9) { // jmp + rel32, Near jump with the target
: :
: : /*
: :
: : SEH64!ILT+15(?CallThatFunctionYAHXZ):
: :
: : 00000000`00401014 e957000000 jmp SEH64!CallThatFunction (000000
: : 00`00401070)
: :
: : SEH64!CallThatFunction [d:/study/win64/seh64/seh64.cpp @ 11]:
: :
: : 00000000`00401070 4057 push rdi
: :
: : 00000000`00401072 4883ec40 sub rsp,40h
: :
: : 00000000`00401076 488bfc mov rdi,rsp
: :
: : */
: :
: : PBYTE pbNew = pbCode + 5 + *(INT32 *)&pbCode[1];
: :
: : return detour_skip_jmp(pbNew, ppGlobals);
: :
: : }
: :
: : else if (pbCode[0] == 0xeb) { // jmp +imm8
: :
: : // These just started appearing with CL13.
: :
: : PBYTE pbNew = pbCode + 2 + *(CHAR *)&pbCode[1];
: :
: : return detour_skip_jmp(pbNew, ppGlobals);
: :
: : }
: :
: : return pbCode;
: :
: : }
: :
: : 知道入口后,detours会调用DetourCopyInstructionEx复制入口处代码
: : 其根据字节可能代表的指令,把相关信息放到s_rceCopyTable表中
: : x64下需要修改的是从0x40到0x4f这几个入口,x64指令集中用他们
: : 作为REX前缀,详细说明参见AMD architecture programmer manual volume 3
: : 1.2.7 REX Prefixes 小节中有详细讨论,这儿全部当成单字节前缀即可
: :
: : #ifdef DETOURS_X64 // For Rex Prefix
: : { 0x40, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : { 0x41, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : { 0x42, ENTRY_CopyBytesPrefix }, // REX Prefixes
: :
: : { 0x43, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : { 0x44, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : { 0x45, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : { 0x46, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : { 0x47, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : { 0x48, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : { 0x49, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : { 0x4A, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : { 0x4B, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : { 0x4C, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : { 0x4D, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : { 0x4E, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : { 0x4F, ENTRY_CopyBytesPrefix }, // REX Prefixes
: : #else
: :
: : 而对FF开始的far indirect jmp/call 指令,x64也跟x86不同
: :
: : PBYTE CDetourDis::CopyFF(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
: :
: : { // CALL /2
: :
: : // CALL /3
: :
: : // INC /0
: :
: : // JMP /4
: :
: : // JMP /5
: :
: : // PUSH /6
: :
: : (void)pEntry;
: :
: : if (0x15 == pbSrc[1] || 0x25 == pbSrc[1]) { // CALL [], JMP []
: :
: : #ifdef DETOURS_X64
: :
: : DWORD dwOffset = *((PDWORD)&pbSrc[2]);
: :
: : *m_ppbTarget = (PBYTE)*((PDWORD_PTR)(pbSrc + 6 + dwOffset));
: :
: : #else
: :
: : PBYTE *ppbTarget = *(PBYTE**)&pbSrc[2];
: :
: : *m_ppbTarget = *ppbTarget;
: :
: : #endif
: :
: : }
: :
: : else if (0x10 == (0x38 & pbSrc[1]) || // CALL /2 --> reg(bits 543) of Mo
: : dR/M == 010
: :
: : 0x18 == (0x38 & pbSrc[1]) || // CALL /3 --> reg(bits 543) of Mo
: : dR/M == 011
: :
: : 0x20 == (0x38 & pbSrc[1]) || // JMP /4 --> reg(bits 543) of Mod
: : R/M == 100
: :
: : 0x28 == (0x38 & pbSrc[1]) // JMP /5 --> reg(bits 543) of Mod
: : R/M == 101
: :
: : ) {
: :
: : *m_ppbTarget = (PBYTE)DETOUR_INSTRUCTION_TARGET_DYNAMIC;
: :
: : }
: :
: : const COPYENTRY ce = { 0xff, ENTRY_CopyBytes2Mod };
: :
: : return (this->*ce.pfCopy)(&ce, pbDst, pbSrc);
: :
: : }
: :
: : 拷贝了原始指令到跳板后,需要在后面增加跳回剩余指令的jmp
: : x86下面detours直接用detour_gen_jmp_immediate函数生成指令
: : 但在x64下面需要修改,因为x64下面指针是64位的,
: : 如果目标地址在当前地址前后2G范围内,可以用32位偏移跳转
: : 否则必须把地址放到内存中,然后在jmp指令指定保存地址的位置
: :
: : detours在通过detour_alloc_trampoline函数分配跳板内存时
: : 会尽量尝试把内存分配在目标函数2G范围内,避免长跳转指令
: : 这样可以确保目标函数大于5字节(near jmp) 时都能工作
: : 但这样一来就无法确保跳板跟hook函数的位置在2G内,
: : 所以x64下面必须处理这些情况,同理照抄mhook代码如下
: :
: : inline PBYTE detour_gen_jmp(PBYTE pbCode, PBYTE pbJumpTo)
: :
: : {
: :
: : PBYTE pbJumpFrom = pbCode + 5;
: :
: : SIZE_T cbDiff = pbJumpFrom > pbJumpTo ? pbJumpFrom - pbJumpTo : pbJumpTo -
: : pbJumpFrom;
: :
: : if (cbDiff <= 0x7fff0000) {
: :
: : *pbCode++ = 0xe9;
: :
: : *((PDWORD)pbCode) = (DWORD)(DWORD_PTR)(pbJumpTo - pbJumpFrom);
: :
: : pbCode += sizeof(DWORD);
: :
: : } else {
: :
: : *pbCode++ = 0xff;
: :
: : *pbCode++ = 0x25;
: :
: : // on x64 we write the relative address of the same location
: :
: : *((PDWORD)pbCode) = (DWORD)0;
: :
: : pbCode += sizeof(DWORD);
: :
: :
: :
: : *((PDWORD_PTR)pbCode) = (DWORD_PTR)(pbJumpTo);
: :
: : pbCode += sizeof(DWORD_PTR);
: :
: : }
: :
: : return pbCode;
: :
: : }
: :
: : 除此之外,还有一些异常情况的处理,例如暂停线程时,
: : 其RIP刚好在跳板或者目标函数入口处,理论上可以使用
: : 与x86相同的机制,不过暂时没法构造环境测试
: :
: : #ifdef DETOURS_X64
: :
: : #define DETOURS_EIP Rip
: : #define DETOURS_EIP_TYPE DWORD64
: :
: : #endif // DETOURS_X64
: :
: : 最后还有一些跟细节的处理,例如对ModRm下RIP的处理
: : 回头加上再一起放出完整可用的代码吧
: :
: : Reference
: :
: : 1. Microsoft Research Detours Package
: : http://research.microsoft.com/research/downloads/Details/d36340fb-4d3c-4ddd-bf5b-1db25d03713d/Details.aspx
: :
: : 2. Mhook, an API hooking library, V2.0
: : http://codefromthe70s.org/mhook2.asp
: :
: : 3. AMD64 Architecture Programmer’s Manual Volume 3: General-Purpose and System Instructions
: :
: : 4. Everything You Need To Know To Start Programming 64-Bit Windows Systems, Matt Pietrek
: : http://msdn.microsoft.com/msdnmag/issues/06/05/x64/default.aspx?print=true&loc=null
: : . 生命的意义在于 // ____/ //_ / //_/ http://flier_lu.blogcn.com .
: : . 希望 / / /___/_/// / //_/__ __ _ _★ .
: : . 工作 / / ____// / / // / /'__`/ //`'_/ .
: : . 爱你的人 / / /___/ / / /___/ / /// __// / / // .
: : . 和你爱的人 / /___/ / /_____/ /__/ /____/ / /_/ .
: : . …… //___/ //_____///__///____/ //_/[email protected] .
: :
: :
: : ※ 修改:·flier 于 Aug 3 01:01:35 修改本文·[FROM: 221.226.232.*]
: : ※ 来源:·水木社区 newsmth.net·[FROM: 221.226.232.*]
:
:
: --
:
: ※ 来源:·水木社区 newsmth.net·[FROM: 166.111.8.*]
--
- 不谈金钱,不谈妇女,不谈琐事
※ 来源:·水木社区 newsmth.net·[FROM: 219.232.52.*]
发信人: Quaful (夸父|嗯), 信区: MSDN
标 题: Re: Detours x64 [Draft]
发信站: 水木社区 (Fri Aug 3 09:17:44 2007), 站内
问一下,这种方法有什么好处吗?呵呵
可以不修改入口代码(如果用hardware breakpoint?)
【 在 peach (换台机器挂站) 的大作中提到: 】
: 最近也折腾了一些这方面的东西,但不是64位的
: 有些想法,正好拿出来
: API HOOK 还可以用另外一种方法,虽然也会用到 detours 相关的技术,不过性能上有不少折扣
: ...................
--
※ 来源:·水木社区 newsmth.net·[FROM: 202.165.107.*]
发信人: peach (换台机器挂站), 信区: MSDN
标 题: Re: Detours x64 [Draft]
发信站: 水木社区 (Fri Aug 3 09:26:12 2007), 站内
好处不多,只是一种方法而已,可能会有它的适用场合。
但使用 hardware breakpoint 的时候会好处多多的
1、可以不修改入口代码
2、可以灵活的控制Hook与否
3、再进一步,都可以使用单步执行中断,自己调试自己。
我之所以弄这些,是因为最近在写脱壳程序来自动脱 asprotect 的壳。脱壳代码是个 dll ,注入到远程进程后,自己调试自己进行脱壳,这些方法还是很方便实用的。
【 在 Quaful (夸父|嗯) 的大作中提到: 】
: 标 题: Re: Detours x64 [Draft]
: 发信站: 水木社区 (Fri Aug 3 09:17:44 2007), 站内
:
: 问一下,这种方法有什么好处吗?呵呵
: 可以不修改入口代码(如果用hardware breakpoint?)
:
: 【 在 peach (换台机器挂站) 的大作中提到: 】
: : 最近也折腾了一些这方面的东西,但不是64位的
: : 有些想法,正好拿出来
: : API HOOK 还可以用另外一种方法,虽然也会用到 detours 相关的技术,不过性能上有不少折扣
: : ...................
:
: --
:
: ※ 来源:·水木社区 newsmth.net·[FROM: 202.165.107.*]
--
※ 来源:·水木社区 newsmth.net·[FROM: 166.111.8.*]
发信人: bbinn (明天的明天), 信区: MSDN
标 题: Re: Detours x64 [Draft]
发信站: 水木社区 (Fri Aug 3 09:41:02 2007), 站内
还是这个好啊,实现起来也容易。
【 在 Quaful (夸父|嗯) 的大作中提到: 】
: 标 题: Re: Detours x64 [Draft]
: 发信站: 水木社区 (Fri Aug 3 09:17:44 2007), 站内
:
: 问一下,这种方法有什么好处吗?呵呵
: 可以不修改入口代码(如果用hardware breakpoint?)
:
: 【 在 peach (换台机器挂站) 的大作中提到: 】
: : 最近也折腾了一些这方面的东西,但不是64位的
: : 有些想法,正好拿出来
: : API HOOK 还可以用另外一种方法,虽然也会用到 detours 相关的技术,不过性能上有不少折扣
: : ...................
:
: --
:
: ※ 来源:·水木社区 newsmth.net·[FROM: 202.165.107.*]
--
- 不谈金钱,不谈妇女,不谈琐事
※ 来源:·水木社区 newsmth.net·[FROM: 219.232.52.*]
发信人: flier (小海 [渴望并不存在的完美]), 信区: MSDN
标 题: Re: Detours x64 [Draft]
发信站: 水木社区 (Fri Aug 3 09:44:47 2007), 站内
硬件断点的话,同时支持数有限,只适用于小规模应用情况
我前段也写过一个进程内硬件断点抓指令和数据访问的,
效果不错但真要同时处理一堆入口,得切换来切换去挺麻烦
如果有类似需求,我考虑的另外一个解决方案是利用VM的支持
强制把os切换到VM guest模式下,通过注入特权指令
让目标进程跳回到VMM的VMExit处理模式下来获取控制权
优点是完全硬件支持理论上对被调试进程透明难以检测
缺点是实现较为复杂,需要有核心态驱动提供后台支持
不过技术上应该是完全可行的,有rootkit已经用上类似技术
就目前来说大部分应用程序还没有考虑到对硬件VM的检测
应该还是能工作一段时间的,呵呵,也就赶个早而已
等以后硬件VM大规模使用,到时候又是另外的头痛问题 :P
【 在 peach (换台机器挂站) 的大作中提到: 】
: 标 题: Re: Detours x64 [Draft]
: 发信站: 水木社区 (Fri Aug 3 09:26:12 2007), 站内
:
: 好处不多,只是一种方法而已,可能会有它的适用场合。
: 但使用 hardware breakpoint 的时候会好处多多的
:
: 1、可以不修改入口代码
: 2、可以灵活的控制Hook与否
: 3、再进一步,都可以使用单步执行中断,自己调试自己。
:
: 我之所以弄这些,是因为最近在写脱壳程序来自动脱 asprotect 的壳。脱壳代码是个 dll ,注入到远程进程后,自己调试自己进行脱壳,这些方法还是很方便实用的。
:
:
: 【 在 Quaful (夸父|嗯) 的大作中提到: 】
: : 标 题: Re: Detours x64 [Draft]
: : 发信站: 水木社区 (Fri Aug 3 09:17:44 2007), 站内
: :
: : 问一下,这种方法有什么好处吗?呵呵
: : 可以不修改入口代码(如果用hardware breakpoint?)
: :
: : 【 在 peach (换台机器挂站) 的大作中提到: 】
: : : 最近也折腾了一些这方面的东西,但不是64位的
: : : 有些想法,正好拿出来
: : : API HOOK 还可以用另外一种方法,虽然也会用到 detours 相关的技术,不过性能上有不少折扣
: : : ...................
: :
: : --
: :
: : ※ 来源:·水木社区 newsmth.net·[FROM: 202.165.107.*]
:
:
: --
:
: ※ 来源:·水木社区 newsmth.net·[FROM: 166.111.8.*]
--
. 生命的意义在于 // ____/ //_ / //_/ http://flier_lu.blogcn.com .
. 希望 / / /___/_/// / //_/__ __ _ _★ .
. 工作 / / ____// / / // / /'__`/ //`'_/ .
. 爱你的人 / / /___/ / / /___/ / /// __// / / // .
. 和你爱的人 / /___/ / /_____/ /__/ /____/ / /_/ .
. …… //___/ //_____///__///____/ //_/
[email protected] .
※ 来源:·水木社区 newsmth.net·[FROM: 218.104.127.*]
发信人: peach (换台机器挂站), 信区: MSDN
标 题: Re: Detours x64 [Draft]
发信站: 水木社区 (Fri Aug 3 09:55:18 2007), 站内
【 在 flier (小海 [渴望并不存在的完美]) 的大作中提到: 】
: 标 题: Re: Detours x64 [Draft]
: 发信站: 水木社区 (Fri Aug 3 09:44:47 2007), 站内
:
: 硬件断点的话,同时支持数有限,只适用于小规模应用情况
: 我前段也写过一个进程内硬件断点抓指令和数据访问的,
: 效果不错但真要同时处理一堆入口,得切换来切换去挺麻烦
没错,适用场合有限
:
: 如果有类似需求,我考虑的另外一个解决方案是利用VM的支持
: 强制把os切换到VM guest模式下,通过注入特权指令
: 让目标进程跳回到VMM的VMExit处理模式下来获取控制权
:
: 优点是完全硬件支持理论上对被调试进程透明难以检测
: 缺点是实现较为复杂,需要有核心态驱动提供后台支持
: 不过技术上应该是完全可行的,有rootkit已经用上类似技术
想法很好 :) 你若有时间给大家写一个吧
:
: 就目前来说大部分应用程序还没有考虑到对硬件VM的检测
: 应该还是能工作一段时间的,呵呵,也就赶个早而已
: 等以后硬件VM大规模使用,到时候又是另外的头痛问题 :P
不管什么东西,一旦流行,新的问题就会接踵而至啊
:
: 【 在 peach (换台机器挂站) 的大作中提到: 】
: : 标 题: Re: Detours x64 [Draft]
: : 发信站: 水木社区 (Fri Aug 3 09:26:12 2007), 站内
: :
: : 好处不多,只是一种方法而已,可能会有它的适用场合。
: : 但使用 hardware breakpoint 的时候会好处多多的
: :
: : 1、可以不修改入口代码
: : 2、可以灵活的控制Hook与否
: : 3、再进一步,都可以使用单步执行中断,自己调试自己。
: :
: : 我之所以弄这些,是因为最近在写脱壳程序来自动脱 asprotect 的壳。脱壳代码是个 dll ,注入到远程进程后,自己调试自己进行脱壳,这些方法还是很方便实用的。
: :
: :
: : 【 在 Quaful (夸父|嗯) 的大作中提到: 】
: : : 标 题: Re: Detours x64 [Draft]
: : : 发信站: 水木社区 (Fri Aug 3 09:17:44 2007), 站内
: : :
: : : 问一下,这种方法有什么好处吗?呵呵
: : : 可以不修改入口代码(如果用hardware breakpoint?)
: : :
: : : 【 在 peach (换台机器挂站) 的大作中提到: 】
: : : : 最近也折腾了一些这方面的东西,但不是64位的
: : : : 有些想法,正好拿出来
: : : : API HOOK 还可以用另外一种方法,虽然也会用到 detours 相关的技术,不过性能上有不少折扣
: : : : ...................
: : :
: : : --
: : :
: : : ※ 来源:·水木社区 newsmth.net·[FROM: 202.165.107.*]
: :
: :
: : --
: :
: : ※ 来源:·水木社区 newsmth.net·[FROM: 166.111.8.*]
:
:
: --
: . 生命的意义在于 // ____/ //_ / //_/ http://flier_lu.blogcn.com .
: . 希望 / / /___/_/// / //_/__ __ _ _★ .
: . 工作 / / ____// / / // / /'__`/ //`'_/ .
: . 爱你的人 / / /___/ / / /___/ / /// __// / / // .
: . 和你爱的人 / /___/ / /_____/ /__/ /____/ / /_/ .
: . …… //___/ //_____///__///____/ //_/[email protected] .
:
:
: ※ 来源:·水木社区 newsmth.net·[FROM: 218.104.127.*]
--
※ 来源:·水木社区 newsmth.net·[FROM: 166.111.8.*]
发信人: flier (小海 [渴望并不存在的完美]), 信区: MSDN
标 题: Re: Detours x64 [Draft]
发信站: 水木社区 (Fri Aug 3 10:11:05 2007), 站内
【 在 peach (换台机器挂站) 的大作中提到: 】
: 没错,适用场合有限
: 想法很好 :) 你若有时间给大家写一个吧
-_-b
这块内容前段倒是看过一些,
但从头弄一个出来太麻烦了,
回头找找有没有现成的改改 :S
: 不管什么东西,一旦流行,新的问题就会接踵而至啊
: ...................
--
. 生命的意义在于 // ____/ //_ / //_/ http://flier_lu.blogcn.com .
. 希望 / / /___/_/// / //_/__ __ _ _★ .
. 工作 / / ____// / / // / /'__`/ //`'_/ .
. 爱你的人 / / /___/ / / /___/ / /// __// / / // .
. 和你爱的人 / /___/ / /_____/ /__/ /____/ / /_/ .
. …… //___/ //_____///__///____/ //_/
[email protected] .
※ 来源:·水木社区 newsmth.net·[FROM: 218.104.127.*]
发信人: chice (do the right thing), 信区: MSDN
标 题: Re: Detours x64 [Draft]
发信站: 水木社区 (Fri Aug 10 10:33:17 2007), 站内
赞啊!
不过vista里面搞钩子好像跟UAC总是不和谐……
【 在 flier (小海 [渴望并不存在的完美]) 的大作中提到: 】
: 该死的路径依赖,为了折腾另外一个问题,不得不先把这个搞定 :S
: Detours我就不介绍了,MSR放出的2.1 Express版本不支持64位
: 而据某人发邮件问,要10000刀才给授权,基本也不用想了 -_-b
: ...................
--
理论上,理论与实际没有差距
实际上,理论与实际差距很大……
※ 来源:·水木社区 newsmth.net·[FROM: 68.181.255.*]
发信人: laoduan (铁鞋踏破也要找到你), 信区: MSDN
标 题: Re: Detours x64 [Draft]
发信站: 水木社区 (Sun Aug 12 20:45:38 2007), 站内
一点提醒:使用SEH机制,效率可能会有些折扣。。。
【 在 peach (换台机器挂站) 的大作中提到: 】
: 最近也折腾了一些这方面的东西,但不是64位的
: 有些想法,正好拿出来
: API HOOK 还可以用另外一种方法,虽然也会用到 detours 相关的技术,不过性能上有不少折扣
: ...................
--
谨代表《金瓶梅》剧组感谢BTV和狐媚导演,是他们耗费了大量的
人力、物力,帮我们选出了如此合适的李萍儿和潘金莲人选。。。
※ 来源:·水木社区 newsmth.net·[FROM: 123.113.203.*]
发信人: laoduan (铁鞋踏破也要找到你), 信区: MSDN
标 题: Re: Detours x64 [Draft]
发信站: 水木社区 (Sun Aug 12 20:47:18 2007), 站内
用VM面临着一个大问题,那就是I家和A家的做法并不兼容。。。
【 在 flier (小海 [渴望并不存在的完美]) 的大作中提到: 】
: 硬件断点的话,同时支持数有限,只适用于小规模应用情况
: 我前段也写过一个进程内硬件断点抓指令和数据访问的,
: 效果不错但真要同时处理一堆入口,得切换来切换去挺麻烦
: ...................
--
谨代表《金瓶梅》剧组感谢BTV和狐媚导演,是他们耗费了大量的
人力、物力,帮我们选出了如此合适的李萍儿和潘金莲人选。。。
※ 修改:·laoduan 于 Aug 12 21:24:13 修改本文·[FROM: 123.113.203.*]
※ 来源:·水木社区 newsmth.net·[FROM: 123.113.203.*]
发信人: flier (小海 [渴望并不存在的完美]), 信区: MSDN
标 题: Re: Detours x64 [Draft]
发信站: 水木社区 (Mon Aug 13 01:15:18 2007), 站内
其实还好了,虽然一些细节上有出入,
但大的功能方面基本能对应上就行
貌似xen里面已经做了个抽象层来封装
比较麻烦的是对I/O的处理,
这块貌似大家都还没太好办法
【 在 laoduan (铁鞋踏破也要找到你) 的大作中提到: 】
: 用VM面临着一个大问题,那就是I家和A家的做法并不兼容。。。
--
. 生命的意义在于 // ____/ //_ / //_/ http://flier_lu.blogcn.com .
. 希望 / / /___/_/// / //_/__ __ _ _★ .
. 工作 / / ____// / / // / /'__`/ //`'_/ .
. 爱你的人 / / /___/ / / /___/ / /// __// / / // .
. 和你爱的人 / /___/ / /_____/ /__/ /____/ / /_/ .
. …… //___/ //_____///__///____/ //_/
[email protected] .
※ 来源:·水木社区 newsmth.net·[FROM: 221.226.232.*]
发信人: laoduan (铁鞋踏破也要找到你), 信区: MSDN
标 题: Re: Detours x64 [Draft]
发信站: 水木社区 (Mon Aug 13 23:06:17 2007), 站内
等VT-d和VMDq出来。。。
【 在 flier (小海 [渴望并不存在的完美]) 的大作中提到: 】
: 其实还好了,虽然一些细节上有出入,
: 但大的功能方面基本能对应上就行
: 貌似xen里面已经做了个抽象层来封装
: ...................
--
谨代表《金瓶梅》剧组感谢BTV和狐媚导演,是他们耗费了大量的
人力、物力,帮我们选出了如此合适的李萍儿和潘金莲人选。。。
※ 来源:·水木社区 newsmth.net·[FROM: 123.113.203.*]