如何通过调试进程来注入DLL?

yuzl32 2010-02-06 10:48:26
在《Windows核心编程》第22章第6小节中有这么一段描述:

22.6 把DLL作为调试器来注入

调试程序能够对被调试的进程执行特殊的操作。当被调试进程加载时,在被调试进程的地址空间已经作好准备,但是被调试进程的主线程尚未执行任何代码之前,系统将自动将这个情况通知调试程序。这时,调试程序可以强制将某些代码插入被调试进程的地址空间中(比如使用WriteProcessMemory函数来插入),然后使被调试进程的主线程执行该代码。

这种方法要求你对被调试线程的CONTEXT结构进行操作,意味着必须编写特定CPU的代码。必须修改你的源代码,使之能够在不同的CPU平台上正确地运行。另外,必须对你想让被调试进程执行的机器语言指令进行硬编码。而且调试程序与它的被调试程序之间必须存在固定的关系。如果调试程序终止运行,Windows将自动撤消被调试进程。而你则无法阻止它。

根据上面的原理,下面的代码哪里写错了,一直都不能把DLL注入到目标进程中:

#include <windows.h>
#include <strsafe.h>
#include <stddef.h>

#pragma comment(lib,"strsafe")

//B8 00000000 mov eax, &szDllPath
//50 push eax
//B9 00000000 mov ecx, &LoadLibrary
//FFD1 call ecx
//CC int3

typedef struct _INJECT_CODE
{
BYTE byMOV_EAX;
DWORD dwMOV_EAX_VALUE;
BYTE byPUSH_EAX;
BYTE byMOV_ECX;
DWORD dwMOV_ECX_VALUE;
WORD wCALL_ECX;
BYTE byINT3;
CHAR szDllPath[MAX_PATH];
}INJECT_CODE,*PINJECT_CODE;

BOOL InjectDebuggeeCode(HANDLE hProcess,LPVOID lpBaseAddress,PCHAR szDllPath)
{
BOOL fSuccess = FALSE;
INJECT_CODE ic = {sizeof(ic)};

ic.byMOV_EAX = 0xB8;
ic.dwMOV_EAX_VALUE = (DWORD)lpBaseAddress + offsetof(INJECT_CODE,szDllPath);
ic.byPUSH_EAX = 0x50;
ic.byMOV_ECX = 0xB9;
ic.dwMOV_ECX_VALUE = (DWORD)&LoadLibrary;
ic.wCALL_ECX = 0xD1FF;
ic.byINT3 = 0xCC;
StringCbCopy(ic.szDllPath,MAX_PATH,szDllPath);

fSuccess = WriteProcessMemory(hProcess,lpBaseAddress,&ic,sizeof(ic),NULL);
if(!fSuccess)printf("Error:%d,Inject Debuggee Code Failed.",GetLastError());
fSuccess = FlushInstructionCache(hProcess,lpBaseAddress,sizeof(ic));
if(!fSuccess)printf("Error:%d,Flush Debuggee Code Failed.",GetLastError());
return fSuccess;
}

int main(int argc,char **argv)
{
DWORD dwProcessId = 0;
char *endptr = "\0";
BOOL fSuccess = FALSE,fFirst = TRUE;
LPVOID lpBaseAddress = NULL;
HANDLE hThread = NULL, hProcess = NULL;
DEBUG_EVENT dbgEvent = {0};
CONTEXT ctxOld = {CONTEXT_FULL},ctxNew = {CONTEXT_FULL};
INJECT_CODE ic = {0};
STARTUPINFO si = {sizeof(si)};
PROCESS_INFORMATION pi = {0};

if(argc != 3)
{
printf("Usage:InjDebuggee.exe <PID> <Be Inject Dll Path>");
return 0;
}

dwProcessId = strtol(argv[1],&endptr,10);
fSuccess = DebugActiveProcess(dwProcessId);
if(!fSuccess){printf("Debug Process [%d] Failed.",dwProcessId);return 0;}

//CreateProcess(NULL,"IpMsg.exe",NULL,NULL,FALSE,DEBUG_ONLY_THIS_PROCESS,NULL,NULL,&si,&pi);

//本程序退出时,防止被调试进程也一并退出
DebugSetProcessKillOnExit(FALSE);

while(WaitForDebugEvent(&dbgEvent,INFINITE))
{
switch(dbgEvent.dwDebugEventCode)
{
case CREATE_PROCESS_DEBUG_EVENT :
hProcess = dbgEvent.u.CreateProcessInfo.hProcess;
hThread = dbgEvent.u.CreateProcessInfo.hThread;

//分配内存,填充注入指令
lpBaseAddress = VirtualAllocEx(hProcess,
NULL,
sizeof(INJECT_CODE),
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
if(NULL == lpBaseAddress)
{
printf("Can not alloc enough memory");
return 0;
}
fSuccess = InjectDebuggeeCode(hProcess,lpBaseAddress,argv[2]);
if(!fSuccess) return 0;


//获取当前线程上下文
GetThreadContext(hThread,&ctxOld);
ctxNew = ctxOld;
ctxNew.Eip = (DWORD)lpBaseAddress;

printf("New Eip = 0x%08X\n",ctxNew.Eip);
//设置新的线程上下文
SetThreadContext(hThread,&ctxNew);
break;
case EXCEPTION_DEBUG_EVENT :
if(dbgEvent.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT)
{
if(fFirst)
{
fFirst = FALSE;
ContinueDebugEvent(dbgEvent.dwProcessId,dbgEvent.dwThreadId,DBG_CONTINUE);
continue;
}
else
{
hProcess= OpenProcess(PROCESS_ALL_ACCESS,
FALSE,
dbgEvent.dwProcessId);
hThread = OpenThread(THREAD_ALL_ACCESS,
FALSE,
dbgEvent.dwThreadId);

GetThreadContext(hThread,&ctxNew);
printf("Second Exception Eip = 0x%08X\n",ctxNew.Eip);

//释放内存
VirtualFreeEx(hProcess,
lpBaseAddress,
sizeof(INJECT_CODE),
MEM_RELEASE);

//设置原先的线程上下文
SetThreadContext(hThread,&ctxOld);

CloseHandle(hThread);
CloseHandle(hProcess);

return 0;
}
}
break;
}
ContinueDebugEvent(dbgEvent.dwProcessId,dbgEvent.dwThreadId,DBG_EXCEPTION_NOT_HANDLED);
}
}

...全文
822 29 打赏 收藏 转发到动态 举报
写回复
用AI写文章
29 条回复
切换为时间正序
请发表友善的回复…
发表回复
管哥 2010-08-27
  • 打赏
  • 举报
回复
有可能是系统权限问题
yuzl32 2010-02-25
  • 打赏
  • 举报
回复
今天把之前放下的这个问题再重新审视了一下,结果就解决了!:-) 谢谢各位提供的信息。
解决方案记录在:http://blog.csdn.net/yuzl32/archive/2010/02/24/5323489.aspx中的条目5。
yuzl32 2010-02-24
  • 打赏
  • 举报
回复
to wangk
谢谢你提供的信息,我测试一下。
yxwsbobo 2010-02-10
  • 打赏
  • 举报
回复
...好的


这样看来Section映射 似乎最牛X了
wangk 2010-02-10
  • 打赏
  • 举报
回复
Detours V1.5版本有远线程、调试注入的示例
Detours V2.1有导入表注入的示例

Section映射这个讲起来就烦一点(这称呼是我自己叫的,学名未必叫这个),很抱歉没什么耐心去敲一大段文字。你可以先去学习一下内核关于进程和Dll加载的资料。我记得网上似乎有LdrLoadDll的源码(也许是伪代码)。

把Dll加载过程理解了,基本上你就知道怎么弄了。

yxwsbobo 2010-02-10
  • 打赏
  • 举报
回复
APC注入.... 原来还可以这样


修改导入表 没用过,这个应该是目标启动前修改的吧?


Section映射 这个完全不懂。。 欢迎讲解。。
wangk 2010-02-10
  • 打赏
  • 举报
回复
从全局钩子、远线程、调试注入、修改导入表、APC注入、Section映射

注入的手法是越来越多了。还有手段欢迎补充
wangk 2010-02-10
  • 打赏
  • 举报
回复
Detours V1.5版本有使用调试注入的示例代码:

你去下载跟踪一下即可。

我附上部分代码来证明它的存在:


//
BOOL InjectLibrary(HANDLE hProcess,
HANDLE hThread,
PBYTE pfLoadLibrary,
PBYTE pbData,
DWORD cbData)
{
BOOL fSucceeded = FALSE;
DWORD nProtect = 0;
DWORD nWritten = 0;
CONTEXT cxt;
UINT32 nCodeBase;
PBYTE pbCode;

struct Code
{
BYTE rbCode[128];
union
{
WCHAR wzLibFile[512];
CHAR szLibFile[512];
};
} code;

SuspendThread(hThread);

ZeroMemory(&cxt, sizeof(cxt));
cxt.ContextFlags = CONTEXT_FULL;
if (!GetThreadContext(hThread, &cxt)) {
goto finish;
}

#if VERBOSE
printf(" ContextFlags: %08x\n", cxt.ContextFlags);
printf(" EIP=%04x:%08x ESP=%04x:%08x EBP=%08x\n",
cxt.SegCs & 0xffff, cxt.Eip, cxt.SegSs & 0xffff, cxt.Esp, cxt.Ebp);
printf(" DS=%04x ES=%04x FS=%04x GS=%04x EFL=%08x\n",
cxt.SegDs & 0xffff, cxt.SegEs & 0xffff,
cxt.SegFs & 0xffff, cxt.SegGs & 0xffff,
cxt.EFlags);
printf(" EAX=%08x EBX=%08x ECX=%08x EDX=%08x ESI=%08x EDI=%08x\n",
cxt.Eax, cxt.Ebx, cxt.Ecx, cxt.Edx, cxt.Esi, cxt.Edi);
#endif

nCodeBase = (cxt.Esp - sizeof(code)) & ~0x1fu; // Cache-line align.
pbCode = code.rbCode;

if (pbData) {
CopyMemory(code.szLibFile, pbData, cbData);
pbCode = DetourGenPush(pbCode, nCodeBase + offsetof(Code, szLibFile));
pbCode = DetourGenCall(pbCode, pfLoadLibrary,
(PBYTE)nCodeBase + (pbCode - code.rbCode));
}

pbCode = DetourGenMovEax(pbCode, cxt.Eax);
pbCode = DetourGenMovEbx(pbCode, cxt.Ebx);
pbCode = DetourGenMovEcx(pbCode, cxt.Ecx);
pbCode = DetourGenMovEdx(pbCode, cxt.Edx);
pbCode = DetourGenMovEsi(pbCode, cxt.Esi);
pbCode = DetourGenMovEdi(pbCode, cxt.Edi);
pbCode = DetourGenMovEbp(pbCode, cxt.Ebp);
pbCode = DetourGenMovEsp(pbCode, cxt.Esp);
pbCode = DetourGenJmp(pbCode, (PBYTE)cxt.Eip,
(PBYTE)nCodeBase + (pbCode - code.rbCode));

cxt.Esp = nCodeBase - 4;
cxt.Eip = nCodeBase;

if (!VirtualProtectEx(hProcess, (PBYTE)nCodeBase, sizeof(Code),
PAGE_EXECUTE_READWRITE, &nProtect)) {
goto finish;
}

#if VERBOSE
printf("VirtualProtectEx(%08x) -> %d\n", nProtect, b);
#endif

if (!WriteProcessMemory(hProcess, (PBYTE)nCodeBase, &code, sizeof(Code),
&nWritten)) {
goto finish;
}

#if VERBOSE
printf("code: %08x..%08x (WriteProcess: %d)\n",
nCodeBase, nCodeBase + (pbCode - code.rbCode), nWritten);
#endif

if (!FlushInstructionCache(hProcess, (PBYTE)nCodeBase, sizeof(Code))) {
goto finish;
}

if (!SetThreadContext(hThread, &cxt)) {
goto finish;
}

#if VERBOSE
ZeroMemory(&cxt, sizeof(cxt));
cxt.ContextFlags = CONTEXT_FULL;
b = GetThreadContext(hThread, &cxt);
printf(" EIP=%04x:%08x ESP=%04x:%08x EBP=%08x\n",
cxt.SegCs & 0xffff, cxt.Eip, cxt.SegSs & 0xffff, cxt.Esp, cxt.Ebp);
printf(" DS=%04x ES=%04x FS=%04x GS=%04x EFL=%08x\n",
cxt.SegDs & 0xffff, cxt.SegEs & 0xffff,
cxt.SegFs & 0xffff, cxt.SegGs & 0xffff,
cxt.EFlags);
printf(" EAX=%08x EBX=%08x ECX=%08x EDX=%08x ESI=%08x EDI=%08x\n",
cxt.Eax, cxt.Ebx, cxt.Ecx, cxt.Edx, cxt.Esi, cxt.Edi);
#endif

fSucceeded = TRUE;

finish:
ResumeThread(hThread);
return fSucceeded;
}

/////////////////////////////////////////////////////////////// Injected Code.
//
#pragma check_stack(off)
#pragma pack(push, 8)

typedef HINSTANCE (WINAPI *PROCLOADLIBRARY)(PWCHAR);

typedef struct {
PROCLOADLIBRARY fnLoadLibrary;
WCHAR wzLibFile[MAX_PATH];
} INJLIBINFO, *PINJLIBINFO;

// Calls to the stack-checking routine must be disabled.

static DWORD WINAPI ThreadFunc(PINJLIBINFO pInjLibInfo) {
// There must be less than a page-worth of local
// variables used in this function.
HINSTANCE hinstLib;

// Call LoadLibrary(A/W) to load the DLL.
hinstLib = pInjLibInfo->fnLoadLibrary(pInjLibInfo->wzLibFile);
return((DWORD) hinstLib);
}

#pragma warning(disable: 4702)

static DWORD WINAPI DeadThreadFunc(PINJLIBINFO pInjLibInfo)
{
(void)pInjLibInfo;
x:
goto x;
return 0;
}

// This function marks the memory address after ThreadFunc.
// ThreadFuncCodeSizeInBytes = (PBYTE) AfterThreadFunc - (PBYTE) ThreadFunc.
static void AfterThreadFunc (void) {
}

#pragma pack(pop)
#pragma check_stack

rendao0563 2010-02-09
  • 打赏
  • 举报
回复
而且调试程序与它的被调试程序之间必须存在固定的关系. 重点应该就是这句话. 猜测跟权限相关.
rendao0563 2010-02-08
  • 打赏
  • 举报
回复
InjDebuggee.exe 是你的注入程序 相当于调试器
pid是你的目标程序的进程id
Inject Dll Path是你要注入的dll

建议你查查调试器的Attach做了哪些事情.或者找个调试器的源码瞧瞧.
yuzl32 2010-02-08
  • 打赏
  • 举报
回复
引用 18 楼 rendao0563 的回复:
InjDebuggee.exe 是你的注入程序 相当于调试器
pid是你的目标程序的进程id
Inject Dll Path是你要注入的dll

建议你查查调试器的Attach做了哪些事情.或者找个调试器的源码瞧瞧.

可能我就是这个方面不是很清楚,才找不到问题的所在。DebugActiveProcess在MSDN中似乎也没有特别的说明。我用CreateProcess方式调试目标进程也无法注入DLL。(见源程序中的CreateProcess注释行。)
yuzl32 2010-02-08
  • 打赏
  • 举报
回复
引用 18 楼 rendao0563 的回复:
InjDebuggee.exe 是你的注入程序 相当于调试器
pid是你的目标程序的进程id
Inject Dll Path是你要注入的dll

建议你查查调试器的Attach做了哪些事情.或者找个调试器的源码瞧瞧.

-_-!!
yuzl32 2010-02-07
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 tr0j4n 的回复:]
你这代码叫人怎么检查,除非给你调。
思路检查下,正确就OK。

对照

其实只要单步的话,就能定位出问题所在了。
Java的老兄,VC的IDE还用的惯吧?
[/Quote]

DLL注入方式有多种,你说的方法是通过子进程的方式注入DLL,我问的是通过调试进程方式注入DLL,在《WINDOWS核心编程》中,我就这种没测试成功啊。:-(
MoXiaoRab 2010-02-07
  • 打赏
  • 举报
回复
懒得帮人调试,我要睡觉去了。代码自己拿去对照吧,你的代码我也没细看,从硬盘里拖了个出来,应该是你要的吧

1. 用CreateProcess(CREATE_SUSPENDED)启动目标进程。

2. 找到目标进程的入口,用ImageHlp中的函数可以实现。

3. 将目标进程入口的代码保存起来。

4. 在目标进程的入口写入LoadLibrary(MyDll)实现Dll的注入。

5. 用ResumeThread运行目标进程。

6. 目标进程就运行了LoadLibrary(MyDll),实现DLL的注入。

7. 目标进程运行完LoadLibrary(MyDll)后,将原来的代码写回目标进程的入口。

8. 目标进程Jmp至原来的入口,继续运行程序。

从原理上可以看出,DLL的注入在目标进程的开始就运行了,而且不是用Debug的方案,这样,就没有上面方案的局限性了。该方案的关键在6,7,8三步,实现方法需要监视进程和DLL合作。下面,结合代码进行分析。

在监视进程中,创建FileMapping,用来保存目标进程的入口代码,同时保证DLL中可以访问。在第7步实现将原目标代码写回目标进程的入口。

// 监视程序和DLL共用的结构体

#pragma pack (push ,1) // 保证下面的结构体采用BYTE对齐(必须)

typedef struct

{

BYTE int_PUSHAD; // pushad 0x60

BYTE int_PUSH; // push &szDLL 0x68

DWORD push_Value; // &szDLL = "ApiSpy.dll"的path

BYTE int_MOVEAX; // move eax &LoadLibrary 0xB8

DWORD eax_Value; // &LoadLibrary

WORD call_eax; // call eax 0xD0FF(FF D0) (LoadLibrary("ApiSpy.dll");

BYTE jmp_MOVEAX; // move eax &ReplaceOldCode 0xB8

DWORD jmp_Value; // JMP的参数

WORD jmp_eax; // jmp eax 0xE0FF(FF E0) jmp ReplaceOldCode;

char szDLL[MAX_PATH]; // "ApiSpy.dll"的FullPath

}INJECT_LOADLIBRARY_CODE, *LPINJECT_CODE;



#pragma pack (pop , 1)

//上面结构体的代码为汇编代码,对应的汇编为:
/*
pushad

push szDll

mov eax, &LoadLibraryA

call eax // 实现调用LoadLibrary(szDll)的代码

mov eax, oldentry

jmp eax // 实现在LoadLibrary运行完后, 跳至目标进程的入口继续运行

*/

// FileMaping的结构体

typedef struct

{

LPBYTE lpEntryPoint; // 目标进程的入口地址

BYTE oldcode[sizeof(INJECT_CODE)]; // 目标进程的代码保存

}SPY_MEM_SHARE, * LPSPY_MEM_SHARE;


/*
准备工作:

第一步:用CreateProcess(CREATE_SUSPENDED)启动目标进程。
*/


CreateProcessA(0, szRunFile, 0, 0, FALSE, CREATE_SUSPENDED

0, NULL, &stInfo,

&m_proInfo) ;

// 用CreateProcess启动一个暂停的目标进程

// 找到目标进程的入口点,函数如下

//第二步:找到目标进程的入口,用ImageHlp中的函数可以实现。

pEntryPoint = GetExeEntryPoint(szRunFile);

LPBYTE GetExeEntryPoint(char *filename)

{

PIMAGE_NT_HEADERS pNTHeader;

DWORD pEntryPoint;

PLOADED_IMAGE pImage;



pImage = ImageLoad(filename, NULL);



if(pImage == NULL)

return NULL;

pNTHeader = pImage->FileHeader;

pEntryPoint = pNTHeader->OptionalHeader.AddressOfEntryPoint + pNTHeader->OptionalHeader.ImageBase;

ImageUnload(pImage);

return (LPBYTE)pEntryPoint;

}


// 创建FileMapping

hMap = CreateFileMapping((HANDLE)0xFFFFFFFF, NULL,

PAGE_READWRITE, 0, sizeof(SPY_MEM_SHARE), “MyDllMapView”);



// 保存目标进程的代码

//第三步:将目标进程入口的代码保存起来。

LPSPY_MEM_SHARE lpMap = pMapViewOfFile(hMap,

FILE_MAP_ALL_ACCESS,

0, 0, 0);

ReadProcessMemory(m_proInfo.hProcess, pEntryPoint,

&lpMap->oldcode, sizeof(INJECT_CODE),

&cBytesMoved);

lpMap->lpEntryPoint = pEntryPoint;



// 第四步:在目标进程的入口写入LoadLibrary(MyDll)实现Dll的注入。

// 准备注入DLL的代码

INJECT_CODE newCode;

// 写入MyDll―――用全路径

lstrcpy(newCode.szDLL, szMyDll);

// 准备硬代码(汇编代码)

newCode.int_PUSHAD = 0x60;

newCode.int_PUSH = 0x68;

newCode.int_MOVEAX = 0xB8;

newCode.call_eax = 0xD0FF;

newCode.jmp_MOVEAX = 0xB8;

newCode.jmp_eax = 0xE0FF;

newCode.eax_Value = (DWORD)&LoadLibrary;

newCode.push_Value=(pEntryPoint + offsetof(INJECT_CODE,szDLL));

// 将硬代码写入目标进程的入口

// 修改内存属性

DWORD dwNewFlg, dwOldFlg;



dwNewFlg = PAGE_READWRITE;

VirtualProtectEx(m_proInfo.hProcess, (LPVOID)pEntryPoint, sizeof(DWORD), dwNewFlg, &dwOldFlg);

WriteProcessMemory(m_proInfo.hProcess, pEntryPoint,

&newCode, sizeof(newCode), NULL);//&dwWrited);

VirtualProtectEx(proInfo.hProcess, (LPVOID)pEntryPoint, sizeof(DWORD), dwOldFlg, &dwNewFlg);

// 释放FileMaping 注意,不是Closehandle(hMap)

UnmapViewOfFile(lpMap);

// 继续目标进程的运行

/*
第五步:用ResumeThread运行目标进程。

ResumeThread(m_proInfo.hThread);



在监视进程中就结束了自己的任务,剩下的第6,7,8步就需要在Dll的DllMain中进行配合。

DLL中用来保存数据的结构体
*/
typedef struct{ DWORD lpEntryPoint; DWORD OldAddr; DWORD OldCode[4];}JMP_CODE,* LPJMP_CODE; static JMP_CODE _lpCode;

// 在DllMain的DLL_PROCESS_ATTACH中调用InitApiSpy函数

// 在该函数中实现第6,7,8步


/*
第六步:目标进程就运行了LoadLibrary(MyDll),实现DLL的注入。
*/

int WINAPI DllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpReserved)

{

switch(dwReason)

{

case DLL_PROCESS_ATTACH:

return InitApiSpy();

……

// InitApiSpy函数的实现

BOOL WINAPI InitApiSpy()

{

HANDLE hMap;

LPSPY_MEM_SHARE lpMem;

DWORD dwSize;

BOOL rc;

BYTE* lpByte;



// 取得FileMapping的句柄

hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, 0, “MyDllMapView”);

if(hMap)

{

lpMem = (LPSPY_MEM_SHARE)MapViewOfFile(hMap,

FILE_MAP_ALL_ACCESS,

0, 0, 0);

if(lpMem)

{

//第七步:目标进程运行完LoadLibrary(MyDll)后,将原来的代码写回目标进程的入口。

// 恢复目标进程的入口代码

// 得到mov eax, value代码的地址

_lpCode.OldAddr = (DWORD)((BYTE*)lpMem->lpEntryPoint + offsetof(INJECT_CODE, jmp_MOVEAX));

_lpCode.lpEntryPoint = (DWORD)lpMem->lpEntryPoint;

// 保存LoadLibrary()后面的代码

memcpy(&_lpCode.OldCode, (BYTE*)lpMem->oldcode + offsetof(INJECT_CODE, jmp_MOVEAX), 2*sizeof(DWORD));

// 恢复目标进程的入口代码

rc = WriteProcessMemory(GetCurrentProcess(), lpMem->lpEntryPoint, lpMem->oldcode, sizeof(INJECT_CODE), &dwSize);

lpByte = (BYTE*)lpMem->lpEntryPoint + offsetof(INJECT_CODE, jmp_MOVEAX);

UnmapViewOfFile(lpMem);

}

CloseHandle(hMap);

}



// 实现自己Dll的其他功能,如导入表的替换

// ……

// 将LoadLibrary后面的代码写为转入处理程序中

// 指令为:mov eax, objAddress

// jmp eax

{

BYTE* lpMovEax;

DWORD* lpMovEaxValu;

WORD* lpJmp;

DWORD fNew, fOld;



fNew = PAGE_READWRITE;

lpMovEax = lpByte;

VirtualProtect(lpMovEax, 2*sizeof(DWORD), fNew, &fOld);

*lpMovEax = 0xB8;

lpMovEaxValu = (DWORD*)(lpMovEax + 1);

*lpMovEaxValu = (DWORD)&DoJmpEntryPoint;

lpJmp = (WORD*)(lpMovEax + 5);

*lpJmp = 0xE0FF; // (FF E0)

VirtualProtect(lpMovEax, 2*sizeof(DWORD), fOld, &fNew);

}

return TRUE;

}



// 转入处理程序

DWORD* lpMovEax;

DWORD fNew, fOld;



void __declspec(naked) DoJmpEntryPoint ()

{

// 恢复LoadLibrary后面的代码

_gfNew = PAGE_READWRITE;

_glpMovEax = (DWORD*)_lpCode.OldAddr;

VirtualProtect(_glpMovEax, 2*sizeof(DWORD), _gfNew, &_gfOld);

*_glpMovEax = _lpCode.OldCode[0];

*(_glpMovEax + 1) = _lpCode.OldCode[1];

VirtualProtect(_glpMovEax, 2*sizeof(DWORD), _gfOld, &_gfNew);

//第八步:目标进程Jmp至原来的入口,继续运行程序。

// 跳至目标代码的入口

_asm popad

_asm jmp _lpCode.lpEntryPoint

}


MoXiaoRab 2010-02-07
  • 打赏
  • 举报
回复
你这代码叫人怎么检查,除非给你调。
思路检查下,正确就OK。

对照

其实只要单步的话,就能定位出问题所在了。
Java的老兄,VC的IDE还用的惯吧?
yuzl32 2010-02-07
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 rendao0563 的回复:]
printf("Usage:InjDebuggee.exe <PID> <Be Inject Dll Path>");   

根据你的参数, 猜测你应该是先启动某程序。再取得该pid。那你是如何变成被调试进程的父进程的?

就是上面这个:而且调试程序与它的被调试程序之间必须存在固定的关系。
[/Quote]
我的源程序就是InjDebuggee.c
rendao0563 2010-02-07
  • 打赏
  • 举报
回复
printf("Usage:InjDebuggee.exe <PID> <Be Inject Dll Path>");

根据你的参数, 猜测你应该是先启动某程序。再取得该pid。那你是如何变成被调试进程的父进程的?

就是上面这个:而且调试程序与它的被调试程序之间必须存在固定的关系。
yuzl32 2010-02-07
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 rendao0563 的回复:]
要是好用分都给我OK?
[/Quote]

只要能解决我这个问题,分数一定给!7~8种注入方式就这种方式还没理解,期待你的帮忙,谢谢!呵呵。
yuzl32 2010-02-07
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 rendao0563 的回复:]
C/C++ code//Enable Privilege for inject!BOOL EnablePrivilege(char*PrivilegeName,BOOL IsEnable)
{
HANDLE hToken;
TOKEN_PRIVILEGES tp;
LUID luid;if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|
TOKEN_QUERY| TOKEN_READ,&hToken))
{return FALSE;
}if(!LookupPrivilegeValue(NULL, PrivilegeName,&luid))
{return TRUE;
}

tp.PrivilegeCount=1;
tp.Privileges[0].Luid= luid;
tp.Privileges[0].Attributes= (IsEnable)? SE_PRIVILEGE_ENABLED :0;

AdjustTokenPrivileges(hToken,FALSE,&tp,NULL,NULL,NULL);

CloseHandle(hToken);return (GetLastError()== ERROR_SUCCESS);
}

DWORD GetProcessIdByName(LPCTSTR lpStrName)
{
HANDLE hSnapShot;
PROCESSENTRY32 pe={sizeof(pe)};
hSnapShot=::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);for(BOOL fok=::Process32First(hSnapShot,&pe); fok ;fok=::Process32Next(hSnapShot,&pe))
{if(lstrcmpi(pe.szExeFile , lpStrName)==0)
{return pe.th32ProcessID;
}
}return-1;
}//inject dll to process,szDllPath is full path!bool InjectDllToRemoteProcess(DWORD dwProcessId,LPCSTR szDllPath)
{
HANDLE hRemoteProcess=NULL;//remote process will be injected HANDLE hRemoteThread=NULL;//injected thread! DWORD dwThreadSize=0;

PVOID pRemoteThread=NULL;//remote thread start pointer PVOID pRemoteParam=NULL;//remote thread thread param! DWORD dwWriten=0;
BOOL bRet=FALSE;

CHAR szDllPathCopy[1024]="";
lstrcpy(szDllPathCopy,szDllPath);

EnablePrivilege(SE_DEBUG_NAME,true);//up Privilege
hRemoteProcess= OpenProcess(PROCESS_ALL_ACCESS,false,dwProcessId);if(hRemoteProcess== NULL)
{
USR_IMPORTANT("open process error!");returnfalse;
}//alloc remote param memory,1024 byte for store the dll path! pRemoteParam= VirtualAllocEx(hRemoteProcess,NULL,1024,MEM_COMMIT,PAGE_READWRITE);if(pRemoteParam== NULL)
{
USR_IMPORTANT("faild to alloc memory");returnfalse;
}//write the dll path to remote memory bRet= WriteProcessMemory(hRemoteProcess,pRemoteParam,(LPVOID)szDllPathCopy,1024,&dwWriten);//write param to remote alloced space!if(!bRet)
{
USR_IMPORTANT("faild to write memory");returnfalse;
}//get the loadlibraryA's pointer! pRemoteThread= GetProcAddress(LoadLibrary("kernel32.dll"),"LoadLibraryA");//here must be "LoadLibraryA"!!if(pRemoteThread== NULL)
{
USR_IMPORTANT("faild to get loadlibraryA address!");returnfalse;
}//start the thread! hRemoteThread= CreateRemoteThread(hRemoteProcess,0,0,(DWORD(__stdcall*)(VOID*))pRemoteThread,pRemoteParam,0,&dwWriten);

EnablePrivilege(SE_DEBUG_NAME,false);//down Privilegereturntrue;
}

你的dll提供一个exec接口。参数就是对方进程的名字。
在exec里面调用上面的接口注入进去。
直接rundll32 你的dllname.dll,exec 对方进程名
就可以了。不用再写个exe调用。并且可以直接调试。相当方便。
[/Quote]
谢谢你的关注!你这个的注入方式是通过远程线程的方式,我想了解的是调试进程注入DLL的方式。:-(
rendao0563 2010-02-07
  • 打赏
  • 举报
回复
要是好用分都给我OK?
加载更多回复(9)

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧