代码注入——c++代码注入
代码注入之——c++代码注入
0x00 代码注入和DLL注入的区别
- DLL注入后DLL会通过线程常驻在某个process中,而代码注入完成之后立即消失。
- 代码注入体积小,不占内存
0x01 通过c++编写注入代码
1)编写注入程序
代码如下:
// CodeInjection.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include <iostream>
#include<stdio.h>
#include<Windows.h>
using namespace std;
//Thrad Parameter
typedef struct _THREAD_PARAM
{
FARPROC pFunc[2]; // LoadLibraryA(), GetProcAddress()
char szBuf[4][128]; // "user32.dll", "MessageBoxA", "www.reversecore.com", "ReverseCore"
} THREAD_PARAM, *PTHREAD_PARAM;
//LoadLibrary
typedef HMODULE(WINAPI *PFLOADLIBRARYA)
(
LPCSTR lpLibFileName
);
//GetProcessAddress
typedef HMODULE(WINAPI *PFGETPROCADDRESS)
(HMODULE hModule,LPCSTR lpProNmae );
//MessageBoxA()
typedef int (WINAPI *PFMESSAGEBOXA)
(
HWND hWnd,
LPCSTR lpText,
LPCSTR lpCaption,
UINT uType
);
//Thread Procedure
DWORD WINAPI ThreadProc(LPVOID lParam)
{
PTHREAD_PARAM pParam = (PTHREAD_PARAM)lParam;
HMODULE hMod = NULL;
FARPROC pFunc = NULL;
// LoadLibrary()
hMod = ((PFLOADLIBRARYA)pParam->pFunc[0])(pParam->szBuf[0]); // "user32.dll"
if (!hMod)
return 1;
// GetProcAddress()
pFunc = (FARPROC)((PFGETPROCADDRESS)pParam->pFunc[1])(hMod, pParam->szBuf[1]); // "MessageBoxA"
if (!pFunc)
return 1;
// MessageBoxA()
((PFMESSAGEBOXA)pFunc)(NULL, pParam->szBuf[2], pParam->szBuf[3], 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, };
DWORD dwSize = 0;
hMod = GetModuleHandleA("kernel32.dll");
//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
if (!(hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwPID)))
{
printf("OpenProcess() fail : err_code = %d\n", GetLastError());
return FALSE;
}
//Allocation for THREAD_PARAM
dwSize = sizeof(THREAD_PARAM);
if (!(pRemoteBuf[0]=VirtualAllocEx(hProcess,NULL,dwSize,MEM_COMMIT, PAGE_READWRITE)))
{
printf("VirtualAllocEx() failed :err_code=%d/n", GetLastError());
return FALSE;
}
//WriteProcessMemory
if (!WriteProcessMemory(hProcess, // hProcess
pRemoteBuf[0], // lpBaseAddress
(LPVOID)¶m, // lpBuffer
dwSize, // nSize
NULL))
{
printf("Write THREAD_PARAM to Memory failed :err_code=%d/n",GetLastError());
return FALSE;
}
//Allocation for ThreadProc()
dwSize = (DWORD)InjectCode - (DWORD)ThreadProc;
if (!(pRemoteBuf[1]=VirtualAllocEx(hProcess,NULL,dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE)))
{
printf("Allocation for ThreadProc() failed :err_code=%d/n", GetLastError());
return FALSE;
}
//Write ThreadProc() to Memorary
if (!(WriteProcessMemory(hProcess, pRemoteBuf[1], (LPVOID)ThreadProc, dwSize, NULL)))
{
printf("Write ThreadProc to Memory failed :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_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;
//查看是不是少了参数
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;
}
编译生成名称为CodeInjection.exe的Released文件。
2)将被注入DLL文件和CodeInjection文件放在同一部目录。打开指定要注入的目标程序,使用processExploer查看其PID。
如下图:
可知notePad.exe的PID为16864
3)使用管理权限打开cmd,输入d:转至CodeInjection.exe所在目录,输入CodeInjection.exe 16864
如下图:
很明显,已经成功注入。我们在看看processExlpoer中的结果。如下图:
我们发现注入的Msg.dll并没有驻留在notepade进程中,而是注入完毕就消失了。
0x02 使用OD进行代码注入调试
1)使用OD载入notepad.exe。点击F9正常运行,如下图:
2)点击选项,点击调试设置,点开事件,选择在中断与新线程(代码注入原理就是使用createRemoteThread创建新线程运行)。如下图:
3)依上一节所讲的再次进行代码注入:
4)此时OD停在了CodeInjection.exe程序的开始地址,如下图:
下面就可以对CodeInjection的代码进行逆向分析了。
再次按F9的话,程序就会注入成功。如下图: