首页
社区
课程
招聘
[原创]远程注入dll
发表于: 2012-12-5 19:29 10813

[原创]远程注入dll

2012-12-5 19:29
10813
今天和同事聊天时他说到以前写外挂时用到了远程注入dll的技术,他当时是这样做的:首先通过CreateProcess创建子进程,需要指定CREATE_SUSPENDED,防止主线程启动。然后在子进程分配内存,写入自己加载dll的代码。之后修改子进程入口点的代码,使子进程启动时先跳到加载dll的代码,随后再恢复入口点。这种方法和hook类似,将入口点hook住,来运行自己的代码。

我当时就想到了是否可以修改主线程的EIP来达到这种功能呢。思路如下:获取主线程的CONTEXT,保存CONTEXT中原来的EIP值,修改CONTEXT中的EIP为自己写的代码,然后在自己的代码运行完后跳到保存的EIP处。

代码如下:
1. 创建子进程
CreateProcess(argv[1], NULL, NULL, NULL, FALSE, [B]CREATE_SUSPENDED[/B], NULL, NULL, &SI, &PI)


2. 获取主线程的CONTEXT
Context.ContextFlags = CONTEXT_CONTROL;
GetThreadContext(PI.hThread, &Context);


3. 在子进程中分配空间
Buffer = VirtualAllocEx(PI.hProcess, NULL, sizeof(SHELL_CODE),
			MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

SHELL_CODE是我定义的结构体,szPath是dll的路径,szInstruction是我加载dll的代码
typedef struct _SHELL_CODE
{
	char szPath[MAX_PATH];
	char szInstruction[0x20];
} SHELL_CODE, *PSHELL_CODE;


4. 定义shellcode
CHAR szDllName[] = "injection.dll";
CHAR szShellCode[] =
		"\x60\x68\x12\x34\x56\x78\xb8\x12\x34\x56\x78\xff\xd0\x61\xe9\x12\x34\x56\x78";

szShellCode转化成汇编代码如下所示:
pushad
push 0x78563412
mov eax, 0x78563412
call eax
popad
jmp 0x78563412

0x78563412是我预先填的地址,随后填为真正的地址。

5. 修改shellcode
*(DWORD*)(szShellCode + 2) = (DWORD)Buffer;
*(DWORD*)(szShellCode + 7) = (DWORD)LoadLibraryA;
*(DWORD*)(szShellCode + 15) = Context.Eip -
		(DWORD)((PUCHAR)Buffer + FIELD_OFFSET(SHELL_CODE, szInstruction) + sizeof(szShellCode) - 1);

第一个是填写字符串的地址,第二个是填写LoadLibraryA的地址,第三个是填写jmp到原来的EIP的地址。

6. 将shellcode写到为子进程分配的内存中
SHELL_CODE ShellCode;
CopyMemory(((PSHELL_CODE)&ShellCode)->szPath, szDllName, sizeof(szDllName));
CopyMemory(((PSHELL_CODE)&ShellCode)->szInstruction, szShellCode, sizeof(szShellCode));
WriteProcessMemory(PI.hProcess, Buffer, &ShellCode, sizeof(SHELL_CODE), &NumberOfBytesWritten)


7. 设置主线程CONTEXT的EIP并启动
Context.Eip = (DWORD)(((PSHELL_CODE)Buffer)->szInstruction);
SetThreadContext(PI.hThread, &Context);
ResumeThread(PI.hThread);


整个过程结束,当主线程启动时,会加载我们的dll,随后跳到原来的入口点执行代码。思路很简单,大牛勿喷。如有雷同,应该是我井底之蛙了

放个代码:https://github.com/yorath/DllInjection

Github已更新,改为使用EAX来指向我的shellcode

[课程]FART 脱壳王!加量不加价!FART作者讲授!

收藏
免费 0
支持
分享
最新回复 (17)
雪    币: 10
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
谢谢分享~虽然已经有了
2012-12-5 19:36
0
雪    币: 2120
活跃值: (73)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
嗯 很简单的想法 我想别人应该早就想到了
2012-12-5 19:38
0
雪    币: 270
活跃值: (97)
能力值: ( LV8,RANK:140 )
在线值:
发帖
回帖
粉丝
4
类似病毒创建傀儡进程
2012-12-5 20:36
0
雪    币: 343
活跃值: (40)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
5
Good, 谢谢分享。但是把主线程先挂起了,会不会导致某些环境未初始化完毕加载的dll崩溃?
2012-12-5 23:51
0
雪    币: 83
活跃值: (83)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
6
-_-
我昨晚想到的这方法 居然有人今个就贴出来了,心灵想通
Context.Eip = (DWORD)(((PSHELL_CODE)Buffer)->szInstruction);
改为
Context.Eax = (DWORD)(((PSHELL_CODE)Buffer)->szInstruction);
线程在ring3的第一行代码时,Eax存放的是线程函数起始地址
这个应该更稳妥的,主线程暂停在ntdll空间,由ntdll->EXE入口点 中间还干了事,
昨个我用这个方法修改子线程入口点,也用的是Eip,结果子线程退出时出错,跟了一会才发现子线程返回地址为0
-_-!
2012-12-6 00:41
0
雪    币: 257
活跃值: (67)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
来看看,学习一下
2012-12-6 01:42
0
雪    币: 137
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
不错的代码 以前写过,但是不是利用CONTEXT
2012-12-6 02:09
0
雪    币: 179
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
很简单的想法
2012-12-6 03:31
0
雪    币: 7
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
楼主好样的,膜拜楼主啊
2012-12-6 09:07
0
雪    币: 2120
活跃值: (73)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
11
我这个改EIP试了几个程序是正常的 改成EAX后也运行正常
2012-12-6 09:48
0
雪    币: 2120
活跃值: (73)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
12
或许有吧 但我还没遇到过 现在改成使用EAX应该就不会有问题了
2012-12-6 10:15
0
雪    币: 1157
活跃值: (847)
能力值: ( LV8,RANK:150 )
在线值:
发帖
回帖
粉丝
13
嗯,去年看样本的时候就见到这种方法了啊,典型的傀儡进程
2012-12-6 10:17
0
雪    币: 7
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
恭喜楼主,EAX大法成功,可喜可贺
2012-12-6 10:19
0
雪    币: 7
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
膜拜啊,求大神收我为徒
2012-12-6 10:22
0
雪    币: 2120
活跃值: (73)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
16
这位就是我那2货同事 =。=
2012-12-6 10:24
0
雪    币: 54
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
win7下可以吗?各位都测试过没有?
2012-12-6 11:32
0
雪    币: 2120
活跃值: (73)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
18
我就是用win7测试的呀 32和64都可以
2012-12-6 11:36
0
游客
登录 | 注册 方可回帖
返回
//