【逆向工程核心原理:代码注入】

概念: 代码注入是一种像目标进程插入独立运行代码并使之运行的技术,它一般调用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)&param,                 // 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、注入流程

  1. 命令行运行程序,传入进程参数
  2. InjectCode打开指定进程,在进程中开辟空间,写入ThreadProc代码;再开辟空间,写入代码需要的数据;在指定进程中开启远程线程,执行注入的代码程序;等待线程结束。

0x03、演示执行过程

  • 编译代码(32bit)
    编译

  • 运行notepad并查看PID
    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)&param,                         // 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
  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值