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那部分。。。