Re: windbg ext中怎么调用被调试程序的函数?

Windows内核调试

windbg ext中怎么调用被调试程序的函数?


icecools 2009-03-26, 21:54 下午
我自己写了一个windbg的extension,里面需要调用被调试程序的一个函数来显示东西,但我没有找到相应的函数,只看到在windbg里的.call可以,但是写程序怎么实现啊?
比如我有个函数Func1(void* p)
我用fun = GetExpression ("Fun1")得到函数地址,然后用
GetExpression(args)得到我传的参数的地址,然后con = ReadMemroy得到此地址的值,后面调用
fun(con)的时候总是出错,大家有啥办法吗?谢谢!

Re: windbg ext中怎么调用被调试程序的函数?


格蠹老雷 2009-03-27, 12:47 下午
可以格式化成.call命令,然后用IDebugControl的Execute接口执行。注意,执行.call命令需要私有符号。

Re: windbg ext中怎么调用被调试程序的函数?


icecools 2009-03-31, 11:28 上午
谢谢Raymond.
我参考了网上另一种方法实现了一下,大体为先GetOffsetByName得到函数地址,然后在target上分配一块内存,拼一段调用此函数的代码,执行后int 3返回调试器,调了一下可以工作

Re: windbg ext中怎么调用被调试程序的函数?


guozf 2009-04-02, 09:12 上午
有这种方法的具体的资料么?可以share给我啊?谢谢。

Re: windbg ext中怎么调用被调试程序的函数?


icecools 2009-04-02, 17:43 下午
楼上,贴上程序,给你参考下
char PushCode<img src="/emoticons/emotion-14.gif" alt="Devil [6]" /> = "\x68\x00\x00\x00\x00"; // push 0
char CallCode[9] = "\xBA\xF0\xF0\xAD\xDE" // 0 - MOV EDX, 0xdeadf0f0 (address of remote function)
"\xFF\xD2" // 5 - CALL *EDX
"\xCC"; // 7 - int3
const CHAR *FUNCTION_NAME = "MyFunctionsName; //it has a pointer parameter

//The helper function to write code/date to the target process virtual memory
int WriteDataVirtual(PDEBUG_DATA_SPACES dataSpaces, ULONG64 baseAddr, void *data, ULONG dataLen, ULONG *offset)
{
ULONG tempOff = 0;
ULONG bytesWritten;

while (dataSpaces->WriteVirtual(baseAddr + *offset + tempOff, (PVOID)((ULONG) data + tempOff), dataLen - tempOff, &bytesWritten) == S_OK)
{
tempOff += bytesWritten;
if (tempOff == dataLen)
{
break;
}
}

if (tempOff != dataLen)
{
dprintf("WriteVirtual error!\n");
return -1;
}

*offset += dataLen;
return S_OK;
}

//WINDBG will call the MyFunctionsName
HRESULT CALLBACK mycall(PDEBUG_CLIENT Client, PCSTR args)
{
ULONG64 functionAddr, dagAddr, processHandle, moduleBase;
ULONG eipIndex, typeId, pdagCont;
DEBUG_VALUE eipValue;
size_t totalCodeLen;
CONTEXT context;
void *codeSpace;
bool success = false;
HRESULT result = S_OK;

PDEBUG_SYMBOLS debugSymbols;
PDEBUG_ADVANCED debugAdvanced;
PDEBUG_DATA_SPACES debugDataSpaces;
PDEBUG_REGISTERS debugRegisters;
PDEBUG_SYSTEM_OBJECTS debugSystemObjects;
PDEBUG_CONTROL debugControl;

Client->QueryInterface(__uuidof(IDebugSymbols), (void **) &debugSymbols);
Client->QueryInterface(__uuidof(IDebugAdvanced), (void **) &debugAdvanced);
Client->QueryInterface(__uuidof(IDebugDataSpaces), (void **) &debugDataSpaces);
Client->QueryInterface(__uuidof(IDebugRegisters), (void **) &debugRegisters);
Client->QueryInterface(__uuidof(IDebugSystemObjects), (void **) &debugSystemObjects);
Client->QueryInterface(__uuidof(IDebugControl), (void **) &debugControl);

if (!debugSymbols || !debugAdvanced || !debugDataSpaces || !debugRegisters || !debugSystemObjects || !debugControl)
{
dprintf("Query the interface error!\n");
goto E_RELEASE;
}

//Get the function address
result = debugSymbols->GetOffsetByName(FUNCTION_NAME, &functionAddr);
if (result != S_OK)
{
dprintf("Function not found or ambiguous!\n");
goto E_RELEASE;
}

//Get the pointer variable address
result = debugSymbols->GetOffsetByName(args, &dagAddr);
if (result != S_OK)
{
dprintf("DagName not found or ambiguous!\n");
goto E_RELEASE;
}

//Find the pointer variable's type and the module base including the variable
result = debugSymbols->GetSymbolTypeId(args, &typeId, &moduleBase);
if (result != S_OK)
{
dprintf("GetSymbolTypeId not found or ambiguous!\n");
goto E_RELEASE;
}

//Get the pointer from the variable
result = debugSymbols->ReadTypedDataVirtual(dagAddr, moduleBase, typeId, (PVOID)&pdagCont, 4, NULL);
if (result != S_OK)
{
dprintf("ReadTypedDataVirtual error!\n");
goto E_RELEASE;
}

//Get the thread context to prepare for call target function then restore the current context
result = debugAdvanced->GetThreadContext(&context, sizeof(context));
if (result != S_OK)
{
dprintf("GetThreadContexterror!\n");
goto E_RELEASE;
}

//Get target handle
result = debugSystemObjects->GetCurrentProcessHandle(&processHandle);
if (result != S_OK)
{
dprintf("GetCurrentProcessHandle error!\n");
goto E_RELEASE;
}

totalCodeLen = sizeof(PushCode) + sizeof(CallCode);

//Allocate some memory in the target
if (!(codeSpace = VirtualAllocEx((HANDLE) processHandle, NULL, totalCodeLen, MEM_COMMIT, PAGE_EXECUTE_READWRITE )))
{
DWORD error = GetLastError();

LPVOID lpMsgBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL );
dprintf((CHAR *) lpMsgBuf);

dprintf("VirtualAllocEx error!\n");
goto E_RELEASE;
}

ULONG curOffset = 0;

memcpy(&(PushCode[1]), (void *) &(pdagCont), 4);

//Write the following code to target memory(push the parameter to the stack)
//PUSH pVoid
result = WriteDataVirtual(debugDataSpaces, (ULONG64) codeSpace, PushCode, sizeof(PushCode) - 1, &curOffset);
if (result != S_OK)
{
goto E_VFREE;
}

memcpy(&(CallCode[1]), (void *) &functionAddr, 4);
//Write the following code to target memory(call target function and return to debugger)
//MOV EDX, funcitonAddress
//CALL *EDX
//INT 3
result = WriteDataVirtual(debugDataSpaces, (ULONG64) codeSpace, CallCode, sizeof(CallCode) - 1, &curOffset);
if (result != S_OK)
{
goto E_VFREE;
}

//Get EIP value
result = debugRegisters->GetIndexByName("eip", &eipIndex);
if (result != S_OK)
{
dprintf("GetIndexByName error!\n");
goto E_VFREE;
}

result = debugRegisters->GetValue(eipIndex, &eipValue);
if (result != S_OK)
{
dprintf("GetValue error!\n");
goto E_VFREE;
}

// Set the new EIP and go
eipValue.Type = DEBUG_VALUE_INT32;
eipValue.I32 = (ULONG) codeSpace;

result = debugRegisters->SetValue(eipIndex, &eipValue);
if (result != S_OK)
{
dprintf("SetValue error!\n");
goto E_VFREE;
}

//Here we run the code finally!
result = debugControl->SetExecutionStatus(DEBUG_STATUS_GO);
if (result != S_OK)
{
dprintf("SetExecutionStatus error!\n");
goto E_RESTORE;
}

result = debugControl->WaitForEvent(0, INFINITE);

//Return from the target function so we need restore the current thread context
E_RESTORE:
debugAdvanced->SetThreadContext(&context, sizeof(context));

//Do some cleanup work
E_VFREE:
VirtualFreeEx((HANDLE) processHandle, codeSpace, 0, MEM_RELEASE);

E_RELEASE:
if (debugSymbols) debugSymbols->Release();
if (debugAdvanced) debugAdvanced->Release();
if (debugDataSpaces) debugDataSpaces->Release();
if (debugRegisters) debugRegisters->Release();
if (debugSystemObjects) debugSystemObjects->Release();
if (debugControl) debugControl->Release();

return result;
}

Re: windbg ext中怎么调用被调试程序的函数?


icecools 2009-04-02, 17:44 下午
第一行应该是
char PushCode[ 6 ] = "\x68\x00\x00\x00\x00"; // push 0
不知道怎么给替换成图标了

Re: windbg ext中怎么调用被调试程序的函数?


guozf 2009-04-07, 08:21 上午
楼上的老兄,这个方法试验过,源代码可以直接work么?谢谢啊。

Re: windbg ext中怎么调用被调试程序的函数?


guozf 2009-04-07, 08:47 上午
还有,这段程序好像 没有包括如何传递参数啊?

Re: windbg ext中怎么调用被调试程序的函数?


icecools 2009-04-07, 10:00 上午
当然可以工作,你仔细看代码,调用函数接受一个指针做参数,注意pushcode那部分。。。

Powered by Community Server Powered by CnForums.Net