概念: 代码注入是一种像目标进程插入独立运行代码并使之运行的技术,它一般调用CreateRemoteThread() API 实现远程线程形式运行插入的代码,也被称为线程注入。
与DLL注入的区别: DLL注入后,代码和数据都在DLL的数据区,DLL代码可以直接使用。代码注入仅仅是向目标进程插入必要的代码,若想让代码正常运行,必须手动提供代码所需要的数据。
代码注入的优点:
1、占用内存少:注入的代码少,不用包装成DLL。
2、难以查找痕迹:DLL注入可以观察到进程中多了DLL模块
3、其他:就是弔
代码注入(C语言)
0x01、解释一下源代码
// CodeInjection.cpp
#include "windows.h"
#include "stdio.h"
// 这个结构用来传输模块名和模块中的函数名字
/*
FARPROC:是一个系统自带的宏,是函数指针类型(对,你没看错)
pFunc:这个数组用来存储两个API函数地址(往后看就会明白)
szBuf:是存模块名字和字符串这些数据资源
*/
typedef struct _THREAD_PARAM
{
FARPROC pFunc[2]; // LoadLibraryA(), GetProcAddress()
char szBuf[4][128]; // "user32.dll", "MessageBoxA", "www.reversecore.com", "ReverseCore"
} THREAD_PARAM, *PTHREAD_PARAM;
// 定义一个函数指针,返回值是HMODULE
typedef HMODULE (WINAPI *PFLOADLIBRARYA)
(
LPCSTR lpLibFileName
);
// 定义一个函数指针,返回值是FARPROC(函数指针类型)
typedef FARPROC (WINAPI *PFGETPROCADDRESS)
(
HMODULE hModule,
LPCSTR lpProcName
);
// 定义一个函数指针,用来调用MessageBox
typedef int (WINAPI *PFMESSAGEBOXA)
(
HWND hWnd,
LPCSTR lpText,
LPCSTR lpCaption,
UINT uType
);
// 要注入的代码,lParam参数的值就是最上面的结构体
DWORD WINAPI ThreadProc(LPVOID lParam)
{
// lParam从LPVOID强转成PHREAD_PRARM的指针类型
PTHREAD_PARAM pParam = (PTHREAD_PARAM)lParam;
HMODULE hMod = NULL;
FARPROC pFunc = NULL;
// 解析第一个函数:pParam->pFunc[0] 是函数地址;pParam->szBuf[0]是参数,就是模块名字
// LoadLibrary()
hMod = ((PFLOADLIBRARYA)pParam->pFunc[0])(pParam->szBuf[0]); // "user32.dll"
if( !hMod )
return 1;
// 解析第二个函数:pParam->pFunc[1] 是函数地址;pParam->szBuf[0] 是参数,就是函数名字
// GetProcAddress()
// pFunc:返回值是MessageBoxA的函数地址
pFunc = (FARPROC)((PFGETPROCADDRESS)pParam->pFunc[1])(hMod, pParam->szBuf[1]); // "MessageBoxA"
if( !pFunc )
return 1;
// pParam->szBuf[2],pParam->szBuf[3] 是MessageBoxA要显示的字符串
// MessageBoxA()
((PFMESSAGEBOXA)pFunc)(NULL, pParam->szBuf[2], pParam->szBuf[3], MB_OK);
return 0;
}
// 实施注入的函数
BOOL InjectCode(DWORD dwPID)
{
HMODULE hMod = NULL;
// 这个结构体对象就是要传的数据(lParam)
THREAD_PARAM param = {0,};
HANDLE hProcess = NULL;
HANDLE hThread = NULL;
LPVOID pRemoteBuf[2] = {0,};
DWORD dwSize = 0;
// 获取模块句柄
hMod = GetModuleHandleA("kernel32.dll");
// 把模块中的两个API地址找到,放到要传的结构体中
// set THREAD_PARAM
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");
// Open Process(打开要注入程序的进程,dwPID是要注入进程的PID)
if ( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, // dwDesiredAccess
FALSE, // bInheritHandle
dwPID)) ) // dwProcessId
{
printf("OpenProcess() fail : err_code = %d\n", GetLastError());
return FALSE;
}
// Allocation for THREAD_PARAM
// 在进程中开辟一段空间,大小是dwSize,也就是传入结构体数据的大小
// 开辟空间的地址是pRemoteBuf[0]
dwSize = sizeof(THREAD_PARAM);
if( !(pRemoteBuf[0] = VirtualAllocEx(hProcess, // hProcess
NULL, // lpAddress
dwSize, // dwSize
MEM_COMMIT, // flAllocationType
PAGE_READWRITE)) ) // flProtect
{
printf("VirtualAllocEx() fail : err_code = %d\n", GetLastError());
return FALSE;
}
// 把要传入的数据写到开辟空间pRemoteBuf[0]
if( !WriteProcessMemory(hProcess, // hProcess
pRemoteBuf[0], // lpBaseAddress
(LPVOID)¶m, // lpBuffer
dwSize, // nSize
NULL) ) // [out] lpNumberOfBytesWritten
{
printf("WriteProcessMemory() fail : err_code = %d\n", GetLastError());
return FALSE;
}
// Allocation for ThreadProc()
// 开辟一段空间用来存代码
dwSize = (DWORD)InjectCode - (DWORD)ThreadProc;
if( !(pRemoteBuf[1] = VirtualAllocEx(hProcess, // hProcess
NULL, // lpAddress
dwSize, // dwSize
MEM_COMMIT, // flAllocationType
PAGE_EXECUTE_READWRITE)) ) // flProtect
{
printf("VirtualAllocEx() fail : err_code = %d\n", GetLastError());
return FALSE;
}
// 把要注入的代码数据写道pRemoteBuf[1]中
if( !WriteProcessMemory(hProcess, // hProcess
pRemoteBuf[1], // lpBaseAddress
(LPVOID)ThreadProc, // lpBuffer
dwSize, // nSize
NULL) ) // [out] lpNumberOfBytesWritten
{
printf("WriteProcessMemory() fail : err_code = %d\n", GetLastError());
return FALSE;
}
// 在要注入的程序中创建远程线程
// 远程线程的执行函数是注入的代码,参数是pRemoteBuf,也就是刚写入数据的地址
if( !(hThread = CreateRemoteThread(hProcess, // hProcess
NULL, // lpThreadAttributes
0, // dwStackSize
(LPTHREAD_START_ROUTINE)pRemoteBuf[1], // lpStartAddress
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;
}
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;
}
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;
}
注:
1、windows10中,源码只有编译成32位release版本才可以注入成功注入notepad。
2、windows10中,源码只有编译成64位release版本才可以注入成功注入64位程序。
0x02、注入流程
- 命令行运行程序,传入进程参数
- InjectCode打开指定进程,在进程中开辟空间,写入ThreadProc代码;再开辟空间,写入代码需要的数据;在指定进程中开启远程线程,执行注入的代码程序;等待线程结束。
0x03、演示执行过程
-
编译代码(32bit)
-
运行notepad并查看PID
-
执行InjectCode.exe
-
结果
0x04、调试演示
-
载入notepad进程(32bit),F9运行
-
设置新线程断点
-
执行InjectCode.exe
-
调试器断下
注入的ThreadProc代码
参数数据:
0x05、解释使用的API
// 打开进程
HANDLE WINAPI OpenProcess(
__in DWORD dwDesiredAccess, // 要获得该进程的权限
__in BOOL bInheritHandle, // 表示所得到的进程句柄是否可以被继承
__in DWORD dwProcessId // 要打开进程的PID
);
/*
PROCESS_ALL_ACCESS //所有能获得的权限
PROCESS_CREATE_PROCESS //需要创建一个进程
PROCESS_CREATE_THREAD //需要创建一个线程
PROCESS_DUP_HANDLE //重复使用DuplicateHandle句柄
PROCESS_QUERY_INFORMATION //获得进程信息的权限,如它的退出代码、优先级
PROCESS_QUERY_LIMITED_INFORMATION /*获得某些信息的权限,如果获得了PROCESS_QUERY_INFORMATION,也拥有PROCESS_QUERY_LIMITED_INFORMATION权限
PROCESS_SET_INFORMATION //设置某些信息的权限,如进程优先级
PROCESS_SET_QUOTA //设置内存限制的权限,使用SetProcessWorkingSetSize
PROCESS_SUSPEND_RESUME //暂停或恢复进程的权限
PROCESS_TERMINATE //终止一个进程的权限,使用TerminateProcess
PROCESS_VM_OPERATION //操作进程内存空间的权限(可用VirtualProtectEx和WriteProcessMemory)
PROCESS_VM_READ //读取进程内存空间的权限,可使用ReadProcessMemory
PROCESS_VM_WRITE //读取进程内存空间的权限,可使用WriteProcessMemory
SYNCHRONIZE //等待进程终止
*/
LPVOID WINAPI VirtualAllocEx(
__in HANDLE hProcess, // 要开辟空间的进程句柄
__in_opt LPVOID lpAddress, // 想要获取的地址区域
__in SIZE_T dwSize, // 要分配的内存区域的大小(以字节为单位)
__in DWORD flAllocationType, // 内存分配的类型
__in DWORD flProtect // 内存页保护
);
BOOL WINAPI WriteProcessMemory(
__in HANDLE hProcess, // 写入进程的句柄
__in LPVOID lpBaseAddress, // 要写入的地址
__in LPCVOID lpBuffer, // 指向写入的内容
__in SIZE_T nSize, // 写入大小
__out SIZE_T* lpNumberOfBytesWritten // 返回实际写入的字节
);
HANDLE WINAPI CreateRemoteThread(
__in HANDLE hProcess, // 要在指定进程创建远程线程
__in LPSECURITY_ATTRIBUTES lpThreadAttributes, // 线程安全描述字,指向SECURITY_ATTRIBUTES结构的指针
__in SIZE_T dwStackSize, // 线程栈大小,以字节表示。如果此参数为 0 ,则新线程将使用可执行文件的默认大小
__in LPTHREAD_START_ROUTINE lpStartAddress, // 一个LPTHREAD_START_ROUTINE类型的指针,指向在远程进程中执行的函数地址
__in LPVOID lpParameter, // 传入函数需要的参数
__in DWORD dwCreationFlags, // 创建线程的其它标志,为0,创建后,线程会立即运行
__out LPDWORD lpThreadId // 返回线程ID
);
代码注入(汇编)
0x01、要注入的汇编代码
把要注入的代码ThreadProc和需要使用的数据弄成汇编代码
ThreadProc()
00401000 55 push ebp
00401001 8BEC mov ebp,esp
00401003 8B75 08 mov esi,dword ptr ss:[ebp+0x8]
00401006 68 6C6C0000 push 0x6C6C
0040100B 68 33322E64 push 0x642E3233
00401010 68 75736572 push 0x72657375
00401015 54 push esp
00401016 FF16 call dword ptr ds:[esi]
00401018 68 6F784100 push 0x41786F
0040101D 68 61676542 push 0x42656761
00401022 68 4D657373 push 0x7373654D
00401027 54 push esp
00401028 50 push eax
00401029 FF56 04 call dword ptr ds:[esi+0x4]
0040102C 6A 00 push 0x0
0040102E E8 0C000000 call asmtest.0040103F
00401033 . 52 65 76 65 72 73 65 43 6F 72 65 00 ascii "ReverseCore",0 ; 字符串 "ReverseCore"
0040103F > E8 14000000 call asmtest.00401058 ; call
00401044 . 77 77 77 2E 7>ascii "www.reversecor" ; 字符串"www.reversecore.com"
00401052 > 65 gs:
00401053 2E db 2E ; CHAR '.'
00401054 . 63 6F 6D 00 ascii "com",0
00401058 6A 00 PUSH 0 ; - hWnd (0)
0040105A FFD0 CALL EAX ; MessageBoxA(0, "www.reversecore.com", "ReverseCore", 0)
0040105C 33C0 XOR EAX,EAX
0040105E 8BE5 MOV ESP,EBP
00401060 5D POP EBP
00401061 C3 RETN
0x02、分析汇编代码
// ThreadProc栈帧
push ebp
mov ebp,esp
// 第一个参数,创建线程会给ThreadProc传个参数,THREAD_PARAM结构
mov esi,dword ptr ss:[ebp+0x8]
// 压入字符串"user32.dll",因为x86是小端存储,所以压栈的字符串都是反的
push 0x6C6C // "\0\0ll"
push 0x642E3233 // "d.23"
push 0x72657375 // "resu"
// "user32.dll" 字符串地址
push esp
// 调用THREAD_PARAM第一个参数,LoadLibrary函数, 参数就是 "user32.dll",调用结束后EAX是user32.dll句柄
call dword ptr ds:[esi]
// 压入参数 "MessageBoxA"
push 0x41786F
push 0x42656761
push 0x7373654D
// 字符串 "MessageBoxA"
push esp
// 加载的user32.dll模块的句柄
push eax
// 调用第二个函数 GetProcAddress, 调用结束后EAX是MessageBox的函数地址
call dword ptr ds:[esi+0x4]
// 准备调用MessageBox函数
push 0x0 // 第四个参数
call asmtest.0040103F // 利用call指令把下面字符串 "ReverseCore" 的地址压入栈,作为MessageBox的第三个参数,
// 字符串 "ReverseCore"
52 65 76 65 72 73 65 43 6F 72 65 00
call asmtest.00401058 // 利用call指令压入第二个参数 "www.reversecore.com", 这条指令的地址就是0040103F
// 字符串 "www.reversecore.com"
77 77 77 2E 72 65 76 65 72 73 65 63 6F 72 65 2E 63 6F 6D 00
PUSH 0// 第一个参数,这条指令的地址是401058
CALL EAX ; 调用MessageBoxA(0, "www.reversecore.com", "ReverseCore", 0)
// 把MessageBox函数返回值清零
XOR EAX,EAX
// 还原栈帧,函数返回
MOV ESP,EBP
POP EBP
RETN
0x03、扣出二进制代码执行注入
把汇编代码的二进制抠出来,放到注入程序中,用数组方式存储:
#include "windows.h"
#include "stdio.h"
typedef struct _THREAD_PARAM
{
// 相比于c代码注入,这里的字符串数据少了,因为提前把它们写到了汇编代码里
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
};
/*
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
*/
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");
// set THREAD_PARAM
param.pFunc[0] = GetProcAddress(hMod, "LoadLibraryA");
param.pFunc[1] = GetProcAddress(hMod, "GetProcAddress");
// Open Process
if ( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, // dwDesiredAccess
FALSE, // bInheritHandle
dwPID)) ) // dwProcessId
{
printf("OpenProcess() fail : err_code = %d\n", GetLastError());
return FALSE;
}
// Allocation for THREAD_PARAM
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());
return FALSE;
}
if( !(hThread = CreateRemoteThread(hProcess, // hProcess
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;
}
注:
windows10 32位Debug和Release都可以注入成功32位notepad,注入64位notepad失败
windows10 64位Debug和Release都可以注入失败64位notepad,(猜测是因为汇编代码是32位的,字符串压栈造成不能注入,以后改进试试)
0x04、注入结果
0x05、64位改写(但是没成功)
00007FFA204CD97C | 55 | push rbp |
00007FFA204CD97D | 48:8BEC | mov rbp,rsp |
00007FFA204CD980 | 48:8B75 10 | mov rsi,qword ptr ss:[rbp+0x10] |
00007FFA204CD984 | 68 6C6C0000 | push 6C6C |
00007FFA204CD989 | 48:BB 7573657233322E64 | mov rbx,642E323372657375 | rbx:"LdrpInitializeProcess"
00007FFA204CD993 | 53 | push rbx | rbx:"LdrpInitializeProcess"
00007FFA204CD994 | 54 | push rsp |
00007FFA204CD995 | FF16 | call qword ptr ds:[rsi] |
00007FFA204CD997 | 68 6F784100 | push 41786F |
00007FFA204CD99C | 48:BB 4D65737361676542 | mov rbx,426567617373654D | rbx:"LdrpInitializeProcess"
00007FFA204CD9A6 | 53 | push rbx | rbx:"LdrpInitializeProcess"
00007FFA204CD9A7 | 54 | push rsp |
00007FFA204CD9A8 | 50 | push rax |
00007FFA204CD9A9 | FF56 08 | call qword ptr ds:[rsi+8] |
00007FFA204CD9AC | 6A 00 | push 0 |
00007FFA204CD9AE | 52 | push rdx |
00007FFA204CD9AF | E8 0C000000 | call ntdll.7FFA204CD9C0 |
00007FFA204CD9B4 | 52 | push rdx |
00007FFA204CD9B5 | 65:76 65 | jbe ntdll.7FFA204CDA1D |
00007FFA204CD9B8 | 72 73 | jb ntdll.7FFA204CDA2D |
00007FFA204CD9BA | 6543:6F | outsd |
00007FFA204CD9BD | 72 65 | jb ntdll.7FFA204CDA24 |
00007FFA204CD9BF | 00 | db 0 |
00007FFA204CD9C0 | E8 14000000 | call ntdll.7FFA204CD9D9 |
00007FFA204CD9C5 | 77 77 | ja ntdll.7FFA204CDA3E |
00007FFA204CD9C7 | 77 2E | ja ntdll.7FFA204CD9F7 |
00007FFA204CD9C9 | 72 65 | jb ntdll.7FFA204CDA30 |
00007FFA204CD9CB | 76 65 | jbe ntdll.7FFA204CDA32 |
00007FFA204CD9CD | 72 73 | jb ntdll.7FFA204CDA42 |
00007FFA204CD9CF | 65:636F 72 | movsxd ebp,dword ptr gs:[rdi+72] |
00007FFA204CD9D3 | 652E:636F 6D | movsxd ebp,dword ptr gs:[rdi+6D] |
00007FFA204CD9D8 | 00 | db 0 |
00007FFA204CD9D9 | 6A 00 | push 0 |
00007FFA204CD9DB | FFD0 | call rax |
00007FFA204CD9DD | 48:33C0 | xor rax,rax |
00007FFA204CD9E0 | 48:8BE5 | mov rsp,rbp |
00007FFA204CD9E3 | 5D | pop rbp |
00007FFA204CD9E4 | C3 | ret |
0x55,0x48,0x8B,0xEC,0x48,0x8B,0x75,0x10,0x68,0x6C,
0x6C,0x00,0x00,0x48,0xBB,0x75,0x73,0x65,0x72,0x33,
0x32,0x2E,0x64,0x53,0x54,0xFF,0x16,0x68,0x6F,0x78,
0x41,0x00,0x48,0xBB,0x4D,0x65,0x73,0x73,0x61,0x67,
0x65,0x42,0x53,0x54,0x50,0xFF,0x56,0x08,0x6A,0x00,
0x52,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,0x48,0x33,0xC0,
0x48,0x8B,0xE5,0x5D,0xC3