首页
社区
课程
招聘
[原创]代码注入
2021-4-16 21:39 11068

[原创]代码注入

2021-4-16 21:39
11068

代码注入(含汇编注入)

一:简介

代码注入是一种向目标进程插入独立运行的代码并使之运行的技术,它一般调用CreateRemoteThread() API以远程线程形式运行插入的代码,所以也可称为线程注入。

 

向目标进程插入代码和数据,代码以线程过程(Thread Procedure)形式插入,而代码中的数据则以线程参数的形式传入。

 

对于dll注入来说,整个dll都会被插入目标进程,代码和数据共享于内存,所以代码能够正常的运行。与dll注入不同,代码注入仅仅向目标进程注入必要的代码,要想使注入的代码正常运行,还必须将代码中的数据一同注入(并将已注入数据的地址明确告知代码)。

 

使用代码注入的优缺分析:

 

占用的内存少。难以查找痕迹,采用dll注入的话会在目标进程的内存中留下痕迹,很容易就能判断出目标进程是否被执行过注入操作,使用代码注入的话几乎不会留下任何痕迹(还是有方法可以检测的),所以恶意代码中大量使用代码注入技术。

二:普通代码注入示例

简介:查看进程的pid,然后在控制台运行程序:CodeInjection.exe [pid],向对应进程插入一个消息窗口(MessageBoxA)。

(一)源码分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#include <windows.h>
#include <stdio.h>
#include <windef.h>
 
/*
FARPROC 是一个4字节指针,指向一个函数的内存地址,例如
GetProcAddress 的返回类型就是一个FARPROC。
如果你要存放这个地址,可以声明以一个 FARPROC变量来存放。
*/
 
typedef struct _THREAD_PARAM
{
    FARPROC pFunc[2];               // LoadLibraryA(), GetProcAddress(),存放两个API函数的地址
    char    szBuf[4][128];          // "user32.dll", "MessageBoxA", "www.reversecore.com", "ReverseCore" 
} THREAD_PARAM, *PTHREAD_PARAM;
 
typedef HMODULE(WINAPI *PFLOADLIBRARYA)
(
LPCSTR lpLibFileName//LoadLibraryA的函数指针,HMODULE的返回值,调用约定为WINAPI,指针名叫PFLOADLIBRARYA,参数为字符串指针lpLibFileName
);
 
typedef FARPROC(WINAPI *PFGETPROCADDRESS)//同理GetProcAddress()的函数指针
(
HMODULE hModule,//模块句柄
LPCSTR lpProcName//查找的函数名字符串指针
);
 
typedef int (WINAPI *PFMESSAGEBOXA)//MessageBoxA的函数指针
(
HWND hWnd,
LPCSTR lpText,
LPCSTR lpCaption,
UINT uType
);
 
DWORD WINAPI ThreadProc(LPVOID lParam)     //线程过程,用来存放我们的注入代码
{
    PTHREAD_PARAM   pParam = (PTHREAD_PARAM)lParam;   //将传入的指针强制类型转换为我们定义的线程参数结构体类型的指针,其实指针本质都是相同的,只是语言的语法要求
    HMODULE         hMod = NULL;                                              //定义一个hMod来存放模块句柄
    FARPROC         pFunc = NULL;                                                  //定义一个FARPROC类型的变量来存放GetProcAddress的返回值
 
    hMod = ((PFLOADLIBRARYA)pParam->pFunc[0])(pParam->szBuf[0]);   // LoadLibrary("user32.dll")
    if (!hMod)
        return 1;
 
    pFunc = (FARPROC)((PFGETPROCADDRESS)pParam->pFunc[1])(hMod, pParam->szBuf[1]);  // GetProcAddress(hMod, "MessageBoxA");
    if (!pFunc)
        return 1;
 
    ((PFMESSAGEBOXA)pFunc)(NULL, pParam->szBuf[2], pParam->szBuf[3], MB_OK);    // MessageBoxA(NULL, "www.reversecore.com", "ReverseCore", MB_OK);
 
    return 0;
}
 
BOOL InjectCode(DWORD dwPID)
{
    HMODULE         hMod = NULL;
    THREAD_PARAM    param = { 0, };
    HANDLE          hProcess = NULL;
    HANDLE          hThread = NULL;
    LPVOID          pRemoteBuf[2] = { 0, }; //void型的长指针,用来指向分配的内存
    DWORD           dwSize = 0;
 
    hMod = GetModuleHandleA("kernel32.dll");
 
    param.pFunc[0] = GetProcAddress(hMod, "LoadLibraryA");  //给线程参数结构体赋值
    param.pFunc[1] = GetProcAddress(hMod, "GetProcAddress");
    strcpy_s(param.szBuf[0], "user32.dll");
    strcpy_s(param.szBuf[1], "MessageBoxA");
    strcpy_s(param.szBuf[2], "www.reversecore.com");
    strcpy_s(param.szBuf[3], "ReverseCore");
 
    if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwPID)))//根据PID获取进程句柄
    {
        printf("OpenProcess() fail : err_code = %d\n", GetLastError());
        return FALSE;
    }
    dwSize = sizeof(THREAD_PARAM);
    if (!(pRemoteBuf[0] = VirtualAllocEx(hProcess,
        NULL,
        dwSize,
        MEM_COMMIT,
        PAGE_READWRITE))) //在对应的进程内部给线程参数,即注入代码要用到的数据分配空间
    {
        printf("VirtualAllocEx() fail : err_code = %d\n", GetLastError());
        return FALSE;
    }
 
    if (!WriteProcessMemory(hProcess,//将线程参数(注入代码要使用的数据)结构体写入分配的内存
        pRemoteBuf[0],
        (LPVOID)&param,
        dwSize,
        NULL))
    {
        printf("WriteProcessMemory() fail : err_code = %d\n", GetLastError());
        return FALSE;
    }
 
    //就是因为这个的原因,生成的时候必须用release
    dwSize = (DWORD)InjectCode - (DWORD)ThreadProc;//函数名就是函数的起始地址,在内存中紧跟着ThreadProc函数的就是InjectCode,所以首地址相减就能够得到ThreadProc代码占用的空间
    if (!(pRemoteBuf[1] = VirtualAllocEx(hProcess,
        NULL,
        dwSize,
        MEM_COMMIT,
        PAGE_EXECUTE_READWRITE)))//为注入代码在对应进程分配空间
    {
        printf("VirtualAllocEx() fail : err_code = %d\n", GetLastError());
        return FALSE;
    }
 
    if (!WriteProcessMemory(hProcess,
        pRemoteBuf[1],
        (LPVOID)ThreadProc,
        dwSize,
        NULL))//在对应空间中写入代码
    {
        printf("WriteProcessMemory() fail : err_code = %d\n", GetLastError());
        return FALSE;
    }
 
    if (!(hThread = CreateRemoteThread(hProcess, //创建远程线程执行注入代码
        NULL,
        0,
        (LPTHREAD_START_ROUTINE)pRemoteBuf[1],
        pRemoteBuf[0],
        0,
        NULL)))
    {
        printf("CreateRemoteThread() fail : err_code = %d\n", GetLastError());
        return FALSE;
    }
 
    WaitForSingleObject(hThread, INFINITE);
 
    CloseHandle(hThread);
    CloseHandle(hProcess);
 
    return TRUE;
}
 
BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) //设置权限
{
    TOKEN_PRIVILEGES tp;
    HANDLE hToken;
    LUID luid;
 
    if (!OpenProcessToken(GetCurrentProcess(),//打开一个与进程相关联的访问token
        TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
        &hToken))
    {
        printf("OpenProcessToken error: %u\n", GetLastError());
        return FALSE;
    }
 
    if (!LookupPrivilegeValue(NULL,//查找系统对应的权限值并储存到luid中
        lpszPrivilege,
        &luid))
    {
        printf("LookupPrivilegeValue error: %u\n", GetLastError());
        return FALSE;
    }
 
    tp.PrivilegeCount = 1;//将这些都存入到TOKEN_PRIVILEGES结构体中
    tp.Privileges[0].Luid = luid;
    if (bEnablePrivilege)
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;//并设置权限属性
    else
        tp.Privileges[0].Attributes = 0;
 
    if (!AdjustTokenPrivileges(hToken,//启用提权
        FALSE,
        &tp,
        sizeof(TOKEN_PRIVILEGES),
        (PTOKEN_PRIVILEGES)NULL,
        (PDWORD)NULL))
    {
        printf("AdjustTokenPrivileges error: %u\n", GetLastError());
        return FALSE;
    }
 
    if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
    {
        printf("The token does not have the specified privilege. \n");
        return FALSE;
    }
 
    return TRUE;
}
 
int main(int argc, char *argv[])
{
    DWORD dwPID = 0;
 
    if (argc != 2)
    {
        printf("\n USAGE  : %s <pid>\n", argv[0]);
        return 1;
    }
 
    if (!SetPrivilege(SE_DEBUG_NAME, TRUE))
        return 1;
 
    dwPID = (DWORD)atol(argv[1]);//将字符串转换为长整型
    InjectCode(dwPID);
 
    return 0;
}

注:生成可执行文件的时候一定要使用release版本
图片描述

(二)注入和调试演示

1. 注入演示

先运行notepad++.exe,然后使用ProcessExploer查看进程PID

 

图片描述

 

管理员模式运行CMD, 进入对应的文件夹后,输入命令

 

图片描述

 

执行结果
图片描述

2. 调试演示

将notepad拖入,并让其运行起来
图片描述

 

然后点击选项

 

图片描述

 

然后注入代码

 

然后就会断到我们的线程函数

 

图片描述

三:使用汇编语言编写注入代码示例

(一)要注入的汇编分析

随便使用一个程序,拖入OD,我们使用OD来编写我们的注入汇编代码

 

PUSH EBP
MOV EBP,ESP

 

注释:

 

生成注入代码ThreadProc自己的栈帧,可以稍微记下硬编码55 8BEC

 

MOV ESI,DWORD PTR SS:[EBP+8]

 

注释:

 

[EBP+8],ThreadProc函数的唯一一个参数LPVOID lParam,这个参数就是我们定义的线程参数的结构体的地址,将其mov给了esi,那么之后ESI和ESI+4就可以取到我们定义的结构体的两个成员(API的函数地址)这个定义的结构体看后面具体代码

 

[EBP+4]是调用该函数时call压入的返回地址

 

PUSH 00006C6C "\0\0ll"
PUSH 642E3233 "d.23"
PUSH 72657375 "resu"

 

注释:

 

将user32.dll字符串压入栈中(仔细思考一下,结合小端序和栈的排列)

 

这算是一个必须掌握的一个简单技能

 

PUSH ESP

 

注释:

 

将ESP压入栈中,因为从ESP开始是储存的字符串,ESP就是字符串的起始地址,就相当于把字符串压入了栈中,作为下面调用LoadLibraryA()函数的参数

 

CALL DWORD PTR DS:[ESI]

 

注释:

 

调用ESI处 储存的函数地址 对应的函数,LoadLibraryA(),汇编语言调用完函数之后返回值一般都是储存到eax寄存器中

 

PUSH 41786F "\0Axo"

 

PUSH 42656761 "Bega"

 

PUSH 7373654D "sseM"

 

注释:

 

将"MessageBoxA"字符串压入栈中

 

PUSH ESP

 

PUSH EAX

 

CALL DWORD PTR DS:[ESI+4]

 

注释:

 

现在的ESP就是字符串"MessageBoxA"的起始地址,将其压入了栈中作为函数的第二个参数,EAX里面的值是调用LoadLibraryA()函数得到的模块的起始地址,hMod。

 

这里就是GetProcAddress(hMod,"MessageBoxA");

 

接下来,我们就要调用MessageBoxA这个函数了,因为GetProcAddress调用完毕后EAX中储存的已经 是函数MessageBoxA的地址了

 

MessageBoxA(NULL,"www.reversecore.com", "ReverseCore", MB_OK);

 

先压入从右到左的第一个参数MB_OK

 

PUSH 0

 

然后压入"ReverseCore"这个字符串,这里有一个小技巧,可以记住,就是利用call等价于push + jmp的特点

 

假设上一条指令所处:

 

002D002C 6A 00 PUSH 0

 

那么接下来,在下方002D0033处,即call指令之后开始,存放我们的字符串"ReverseCore",存放的区域就是002D0033-002D003F之间

 

然后我们call的话,就直接call 002D003F

 

这样先将字符串“ReverseCore” push进入了栈中,然后有jmp跳转到了地址002D003F处

 

同理,现在我们要压入参数"www.reversecore.com"

 

002D003F-002D0043之间存放指令call 002D0058

 

002D0044-002D0057之间存放我们的字符串"www.reversecore.com"

 

这样既将下面的数据push进入了栈中,还跳转到了下方

 

然后压入第一个参数NULL

 

push 0

 

最后调用我们的MessageBoxA函数

 

CALL EAX

 

之后调用完函数之后,我们要将返回值设为0

 

使用指令XOR EAX, EAX便可以简单并快捷的将返回值设置为0

 

MOV ESP,EBP

 

POP EBP

 

RETN

 

注释:

 

删除栈帧及函数返回

 

所有的汇编指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
004010ED    55               PUSH EBP
004010EE    8BEC             MOV EBP,ESP
004010F0    8B75 08          MOV ESI,DWORD PTR SS:[EBP+8]       ; ESI = pParam           
004010F3    68 6C6C0000      PUSH 6C6C                      
004010F8    68 33322E64      PUSH 642E3233
004010FD    68 75736572      PUSH 72657375
00401102    54               PUSH ESP                           ; - "user32.dll"
00401103    FF16             CALL DWORD PTR DS:[ESI]            ; LoadLibraryA("user32.dll")
00401105    68 6F784100      PUSH 41786F
0040110A    68 61676542      PUSH 42656761
0040110F    68 4D657373      PUSH 7373654D
00401114    54               PUSH ESP                           ; - "MessageBoxA"
00401115    50               PUSH EAX                           ; - hMod
00401116    FF56 04          CALL DWORD PTR DS:[ESI+4]          ; GetProcAddress(hMod, "MessageBoxA")
00401119    6A 00            PUSH 0                             ; - MB_OK (0)
0040111B    E8 0C000000      CALL 0040112C
00401120                     <ASCII>                            ; - "ReverseCore", 0
0040112C    E8 14000000      CALL 00401145
00401131                     <ASCII>                            ; - "www.reversecore.com", 0
00401145    6A 00            PUSH 0                             ; - hWnd (0)
00401147    FFD0             CALL EAX                           ; MessageBoxA(0, "www.reversecore.com", "ReverseCore", 0)
00401149    33C0             XOR EAX,EAX                        
0040114B    8BE5             MOV ESP,EBP
0040114D    5D               POP EBP                            
0040114E    C3               RETN

编辑完了之后, 右键,Copy to executable-All modifications

 

弹出消息框之后点击Copy all

 

然后弹出一个显示所有修改的窗口,我们鼠标右键Save file,即可保存出去

 

然后我们得到shellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
BYTE g_InjectionCode[] =  
    0x55, 0x8B, 0xEC, 0x8B, 0x75, 0x08, 0x68, 0x6C, 0x6C, 0x00
    0x00, 0x68, 0x33, 0x32, 0x2E, 0x64, 0x68, 0x75, 0x73, 0x65
    0x72, 0x54, 0xFF, 0x16, 0x68, 0x6F, 0x78, 0x41, 0x00, 0x68
    0x61, 0x67, 0x65, 0x42, 0x68, 0x4D, 0x65, 0x73, 0x73, 0x54
    0x50, 0xFF, 0x56, 0x04, 0x6A, 0x00, 0xE8, 0x0C, 0x00, 0x00
    0x00, 0x52, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x43, 0x6F
    0x72, 0x65, 0x00, 0xE8, 0x14, 0x00, 0x00, 0x00, 0x77, 0x77
    0x77, 0x2E, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x63
    0x6F, 0x72, 0x65, 0x2E, 0x63, 0x6F, 0x6D, 0x00, 0x6A, 0x00
    0xFF, 0xD0, 0x33, 0xC0, 0x8B, 0xE5, 0x5D, 0xC3 
};

(二)注入的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#include "windows.h" 
#include "stdio.h" 
 
typedef struct _THREAD_PARAM  
    FARPROC pFunc[2];               // LoadLibraryA(), GetProcAddress()函数地址
} THREAD_PARAM, *PTHREAD_PARAM;
 
BYTE g_InjectionCode[] =  
    0x55, 0x8B, 0xEC, 0x8B, 0x75, 0x08, 0x68, 0x6C, 0x6C, 0x00
    0x00, 0x68, 0x33, 0x32, 0x2E, 0x64, 0x68, 0x75, 0x73, 0x65
    0x72, 0x54, 0xFF, 0x16, 0x68, 0x6F, 0x78, 0x41, 0x00, 0x68
    0x61, 0x67, 0x65, 0x42, 0x68, 0x4D, 0x65, 0x73, 0x73, 0x54
    0x50, 0xFF, 0x56, 0x04, 0x6A, 0x00, 0xE8, 0x0C, 0x00, 0x00
    0x00, 0x52, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x43, 0x6F
    0x72, 0x65, 0x00, 0xE8, 0x14, 0x00, 0x00, 0x00, 0x77, 0x77
    0x77, 0x2E, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x63
    0x6F, 0x72, 0x65, 0x2E, 0x63, 0x6F, 0x6D, 0x00, 0x6A, 0x00
    0xFF, 0xD0, 0x33, 0xC0, 0x8B, 0xE5, 0x5D, 0xC3 
}; 
 
BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)   //设置权限
    TOKEN_PRIVILEGES tp; 
    HANDLE hToken; 
    LUID luid; 
 
    if( !OpenProcessToken(GetCurrentProcess(), 
                          TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,  
                          &hToken) ) 
    
        printf("OpenProcessToken error: %u\n", GetLastError()); 
        return FALSE; 
    
 
    if( !LookupPrivilegeValue(NULL,           // lookup privilege on local system 
                              lpszPrivilege,  // privilege to lookup  
                              &luid) )        // receives LUID of privilege 
    
        printf("LookupPrivilegeValue error: %u\n", GetLastError() );  
        return FALSE;  
    
 
    tp.PrivilegeCount = 1
    tp.Privileges[0].Luid = luid; 
    if( bEnablePrivilege ) 
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 
    else 
        tp.Privileges[0].Attributes = 0
 
    // Enable the privilege or disable all privileges. 
    if( !AdjustTokenPrivileges(hToken,  
                               FALSE,  
                               &tp,  
                               sizeof(TOKEN_PRIVILEGES),  
                               (PTOKEN_PRIVILEGES) NULL,  
                               (PDWORD) NULL) ) 
    {  
        printf("AdjustTokenPrivileges error: %u\n", GetLastError() );  
        return FALSE;  
    }  
 
    if( GetLastError() == ERROR_NOT_ALL_ASSIGNED ) 
    
        printf("The token does not have the specified privilege. \n"); 
        return FALSE; 
    }  
 
    return TRUE; 
 
BOOL InjectCode(DWORD dwPID)   //关键注入部分
    HMODULE         hMod            = NULL; 
    THREAD_PARAM    param           = {0,}; 
    HANDLE          hProcess        = NULL; 
    HANDLE          hThread         = NULL; 
    LPVOID          pRemoteBuf[2]   = {0,}; 
 
    hMod = GetModuleHandleA("kernel32.dll"); 
 
    param.pFunc[0] = GetProcAddress(hMod, "LoadLibraryA"); 
    param.pFunc[1] = GetProcAddress(hMod, "GetProcAddress");  //获取两个函数的地址并储存进入自定义的线程参数结构体中                  
 
    if ( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS,               // dwDesiredAccess 
                                  FALSE,                            // bInheritHandle 
                                  dwPID)) )                         // dwProcessId 
    
        printf("OpenProcess() fail : err_code = %d\n", GetLastError());  //根据PID获取进程句柄
        return FALSE; 
    
 
    // Allocation for THREAD_PARAM                            //在对应的进程当中分配内存来存储data
    if( !(pRemoteBuf[0] = VirtualAllocEx(hProcess,                  // hProcess 
                                         NULL,                      // lpAddress 
                                         sizeof(THREAD_PARAM),      // dwSize 
                                         MEM_COMMIT,                // flAllocationType 
                                         PAGE_READWRITE)) )         // flProtect 
    
        printf("VirtualAllocEx() fail : err_code = %d\n", GetLastError()); 
        return FALSE; 
    
 
    if( !WriteProcessMemory(hProcess,                               // hProcess 
                            pRemoteBuf[0],                          // lpBaseAddress 
                            (LPVOID)¶m,                         // lpBuffer 
                            sizeof(THREAD_PARAM),                   // nSize 
                            NULL) )                                 // [out] lpNumberOfBytesWritten 
    
        printf("WriteProcessMemory() fail : err_code = %d\n", GetLastError());  //写入我们的代码要用的数据
        return FALSE; 
    
 
    // Allocation for ThreadProc() 
    if( !(pRemoteBuf[1] = VirtualAllocEx(hProcess,                  // hProcess 
                                         NULL,                      // lpAddress 
                                         sizeof(g_InjectionCode),   // dwSize 
                                         MEM_COMMIT,                // flAllocationType 
                                         PAGE_EXECUTE_READWRITE)) ) // flProtect 
    
        printf("VirtualAllocEx() fail : err_code = %d\n", GetLastError());  //为我们的注入代码分配空间
        return FALSE; 
    
 
    if( !WriteProcessMemory(hProcess,                               // hProcess 
                            pRemoteBuf[1],                          // lpBaseAddress 
                            (LPVOID)&g_InjectionCode,               // lpBuffer 
                            sizeof(g_InjectionCode),                // nSize 
                            NULL) )                                 // [out] lpNumberOfBytesWritten 
    
        printf("WriteProcessMemory() fail : err_code = %d\n", GetLastError());   //写入我们的shellcode
        return FALSE; 
    
 
    if( !(hThread = CreateRemoteThread(hProcess,                    // hProcess    //这里创建远程线程执行我们的shellcode
                                       NULL,                        // lpThreadAttributes 
                                       0,                           // dwStackSize 
                                       (LPTHREAD_START_ROUTINE)pRemoteBuf[1], 
                                       pRemoteBuf[0],               // lpParameter 
                                       0,                           // dwCreationFlags 
                                       NULL)) )                     // lpThreadId 
    
        printf("CreateRemoteThread() fail : err_code = %d\n", GetLastError()); 
        return FALSE; 
    
 
    WaitForSingleObject(hThread, INFINITE);  
 
    CloseHandle(hThread); 
    CloseHandle(hProcess); 
 
    return TRUE; 
 
int main(int argc, char *argv[]) 
    DWORD dwPID     = 0
 
    if( argc != 2
    
        printf("\n USAGE  : %s <pid>\n", argv[0]); 
        return 1
    
 
    // change privilege 
    if( !SetPrivilege(SE_DEBUG_NAME, TRUE) ) 
        return 1
 
    // code injection 
    dwPID = (DWORD)atol(argv[1]); 
    InjectCode(dwPID); 
 
    return 0
}

[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

最后于 2021-4-18 19:14 被SYJ-Re编辑 ,原因:
收藏
点赞4
打赏
分享
最新回复 (1)
雪    币: 299
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
QZ2019 2021-10-11 16:48
2
0
很好很强大
游客
登录 | 注册 方可回帖
返回