首页
社区
课程
招聘
[求助]请教如果用CreateProcess方式注入DLL?只求WIN32汇编代码!谢谢
发表于: 2008-6-7 07:05 12081

[求助]请教如果用CreateProcess方式注入DLL?只求WIN32汇编代码!谢谢

2008-6-7 07:05
12081
请教如果用CreateProcess方式注入DLL?只求WIN32汇编代码!谢谢

最近一个多星期一直在试验这个方法来注入自己的DLL.....

我参考的是网络上一篇流传很久的VC版本...可是一直没成功...搞了快10天了...

希望哪位用 WIN32ASM 实现过此功能的兄弟能帮一把手...谢谢谢谢了.....

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 1
支持
分享
最新回复 (19)
雪    币: 560
活跃值: (359)
能力值: ( LV13,RANK:1370 )
在线值:
发帖
回帖
粉丝
2
.386
.model flat, stdcall
option casemap:none
include windows.inc
include kernel32.inc
include user32.inc
includelib kernel32.lib
includelib user32.lib

.data
szTarget byte 'Notepad', 0
szUser32 byte 'USER32.DLL', 0
szSharedData byte 261 dup (0)

.data?
hModule dword ?
hNewModule dword ?
hProcess dword ?
dwSize dword ?
dwPid dword ?
dwBytesWritten dword ?
dwTid dword ?
.code

HijackedThread proc
invoke LoadLibrary, addr szUser32
invoke DeleteFile, addr szSharedData
invoke MessageBox, 0, addr szTarget, addr szTarget, 0
invoke ExitThread, 0
ret
HijackedThread endp

_entrypoint:
invoke GetModuleHandle, 0
mov hModule, eax
mov edi, eax 
assume edi:ptr IMAGE_DOS_HEADER 
add edi, [edi].e_lfanew
add edi, sizeof dword
add edi, sizeof IMAGE_FILE_HEADER
assume edi:ptr IMAGE_OPTIONAL_HEADER32 
mov eax, [edi].SizeOfImage
mov dwSize, eax
assume edi:NOTHING
invoke GetModuleFileName, 0, addr szSharedData, 261
invoke FindWindow, addr szTarget, 0
invoke GetWindowThreadProcessId, eax, addr dwPid
invoke OpenProcess, PROCESS_ALL_ACCESS, FALSE, dwPid
mov hProcess, eax
invoke VirtualFreeEx, hProcess, hModule, 0, MEM_RELEASE
invoke VirtualAllocEx, hProcess, hModule, dwSize, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE 
mov hNewModule, eax
invoke WriteProcessMemory, hProcess, hNewModule, hModule, dwSize, addr dwBytesWritten
invoke CreateRemoteThread, hProcess, 0, 0, addr HijackedThread, hModule, 0, addr dwTid
invoke ExitProcess, 0
end _entrypoint
2008-6-7 08:09
0
雪    币: 107
活跃值: (419)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
晕.老大你真速度啊...这么大早的.不枉我在这里刷新啊....

我马上试用一下.然后反馈你信息..谢谢你了
2008-6-7 08:21
0
雪    币: 107
活跃值: (419)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
晕...仔细一看..怎么好像是远程线程注入?????

利用CreateProcess方法注入好像没这么简单吧???

要获取OEP,还要建立FILEMAPPING...还要改写代码,然后获取LOADLIBRAY然后还需要DLL动态库里面有一段代码恢复OEP...然后JMP到OEP..然后再启动进程的主线程啊....哥哥!!!
2008-6-7 08:23
0
雪    币: 560
活跃值: (359)
能力值: ( LV13,RANK:1370 )
在线值:
发帖
回帖
粉丝
5
你贴出VC的看看
2008-6-7 08:35
0
雪    币: 205
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
利用CreateProcess创建一个挂起的子进程(即将被注入的进程),你先获取通过获取其加载内存镜像基址(可通过EPROCESS等得到),其后的步骤与你说的差不多。
你把VC版本的拿出来让大伙看看,也许经过修改后可以编译通过的
2008-6-7 09:35
0
雪    币: 107
活跃值: (419)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
实现DLL注入的另一种方法

  

将DLL注入进程技术在实现Api函数的监视程序中不可缺少的一项工作。其中最常见的就是用SetWindowsHookEx函数实现了。不过,该方法的缺点是被监视的目标进程必须有窗口,这样,SetWindowsHookEx才能将DLL注入目标进程中。而且,目标程序已经运行了,那么,在窗口创建之前的Api函数就不能被Hook了。

另外一种方法用Debug方案,就可以实现在程序创建时监视所有的Api了,缺点是必须是目标进程的Debug源,在监视程序终了时,目标进程会无条件终了。最大的缺点就是无法调试注入的DLL。

还有其他多种方案也可以实现DLL的注入,在《Windows核心编程》一书中就介绍了8-9种,其中有一种采用CreateProcess的方法,实现起来比较复杂,但没有上面几种方法的局限性。且可以用其他工具(VC等)调试注入的DLL。下面进行介绍。

原理如下:

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

}

  

这样就实现了原来的目标,将DLL的注入放在目标进程的入口运行,实现了目标进程运行之前运行我们的注入Dll的功能。

  

下面用图形表示在目标进程中代码发生变化的情况。(示意图)

  
监视程序
FileMapping
目标进程
  
第一步
启动目标进程


  
第二步
找到入口

启动(暂停中)
  
第三步
保存代码
目标进程的代码
无变化
  
第四步
写入注入代码
同上
入口代码为:

LoadLibrary(MyDll);

jmp xxxxxxxx

其他原来的代码
  
第五步
运行目标进程
同上
运行LoadLibrary
  
第六步
无变化
无变化
LoadLibrary中处理
  
第七步
无变化
无变化
入口代码被写为原来的代码
  
第7.5步
无变化
无变化
上面jmp xxxxxxxx的代码写为jmp DoJmpEntryPoint
  
第7.9步
无变化
无变化
运行完LoadLibrary后,转入DoJmpEntryPoint函数中处理

在该函数中,将jmp DoJmpEntryPoint的指令恢复为原指令。
  
第八步
无变化
无变化
转入目标进程的入口执行,完成注入目标。
  

  

上面代码为了方便分析原理,未作错误和防干扰的处理。本人利用该方案在9X,NT和2000中实现了一个监视API的输入输出的实用程序.

谢谢laomms兄弟!!!!!
2008-6-7 09:38
0
雪    币: 107
活跃值: (419)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
同时还要谢谢neverqq兄弟.....

大家一起研究一下吧....我郁闷死了..我弄了N个通宵了还是没搞定它...气愤啊....

又一个通宵我累死了..哎..我先睡一下..看中午起床是否有好消息呢
2008-6-7 09:39
0
雪    币: 231
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
用CREATEPROCESS可以用远线程插入
2008-6-7 10:46
0
雪    币: 107
活跃值: (419)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
晕...escript.....那个例子没看明白吗?????

不是远程线程注入...你看那个VC的例子有远程线程插入的影子????????????????
2008-6-7 13:19
0
雪    币: 560
活跃值: (359)
能力值: ( LV13,RANK:1370 )
在线值:
发帖
回帖
粉丝
11
好长的代码,建议找到编译好的程序,用IDA反汇编后结合原来的VC代码翻译一下.
2008-6-7 14:28
0
雪    币: 144
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
等Laomms的ASM
2008-6-7 16:07
0
雪    币: 107
活跃值: (419)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
强烈的期待Laomms老大发出win32asm的代码
2008-6-7 17:24
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
这不是感染pe么 只是往文件的是loadLibrary....感染pe不用改回来 你这还得改回来~~
2008-6-8 18:21
0
雪    币: 249
活跃值: (10)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
15
正解             凑字
2008-6-8 19:19
0
雪    币: 107
活跃值: (419)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
怎么都失踪拉....
2008-6-10 10:35
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
17
Fido 怎么都失踪拉....
11
2023-3-10 01:30
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
18
可以加个Q嘛 
2023-3-10 01:31
0
雪    币: 29
能力值: (RANK:0 )
在线值:
发帖
回帖
粉丝
19
https://www.nb-qiantai.com/
2023-3-10 14:11
0
雪    币: 1440
活跃值: (1401)
能力值: ( LV3,RANK:23 )
在线值:
发帖
回帖
粉丝
20
08年的文章啊,那没事了
2023-3-10 15:10
0
游客
登录 | 注册 方可回帖
返回
//