步骤
1.确定注入进程的上下文,因为要生成机械码,例如x64的机械码,只能注入到64为程序。
2.使用c编写代码。替换掉里面的共享库函数地址。
演示
写一个简单的代码,我是用的是64为环境
#include <windows.h>
int main() {
char text[] = "Hello, World!"; //字符串需要这样声明,保证存储在栈中
char caption[] = "Message Box Example";
int ret = MessageBox(NULL, text, caption, MB_OK);
return 0;
}
反汇编效果如下
现在修改内容
将call main 全部填空,将 mov cs:_imp_MessageBoxA ,的操作数改成特殊值1122334455667788h,以便替换地址
修改后图片
将这个方法转为c byte型数组保存下来
unsigned char main[126] = {
0x55, 0x48, 0x89, 0xE5, 0x48, 0x83, 0xEC, 0x50, 0x90, 0x90, 0x90, 0x90, 0x90, 0x48, 0xB8, 0x48,
0x65, 0x6C, 0x6C, 0x6F, 0x2C, 0x20, 0x57, 0x48, 0x89, 0x45, 0xEE, 0xC7, 0x45, 0xF6, 0x6F, 0x72,
0x6C, 0x64, 0x66, 0xC7, 0x45, 0xFA, 0x21, 0x00, 0x48, 0xB8, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67,
0x65, 0x20, 0x48, 0xBA, 0x42, 0x6F, 0x78, 0x20, 0x45, 0x78, 0x61, 0x6D, 0x48, 0x89, 0x45, 0xD0,
0x48, 0x89, 0x55, 0xD8, 0xC7, 0x45, 0xE0, 0x70, 0x6C, 0x65, 0x00, 0x48, 0x8D, 0x55, 0xD0, 0x48,
0x8D, 0x45, 0xEE, 0x41, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x49, 0x89, 0xD0, 0x48, 0x89, 0xC2, 0xB9,
0x00, 0x00, 0x00, 0x00, 0x48, 0xB8, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0xFF, 0xD0,
0x89, 0x45, 0xFC, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x48, 0x83, 0xC4, 0x50, 0x5D, 0xC3
};
源码
使用下面代码进行注入会弹出对话框
#include <windows.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
int main() {
unsigned char strcode[126] = {
0x55, 0x48, 0x89, 0xE5, 0x48, 0x83, 0xEC, 0x50, 0x90, 0x90, 0x90, 0x90, 0x90, 0x48, 0xB8, 0x48,
0x65, 0x6C, 0x6C, 0x6F, 0x2C, 0x20, 0x57, 0x48, 0x89, 0x45, 0xEE, 0xC7, 0x45, 0xF6, 0x6F, 0x72,
0x6C, 0x64, 0x66, 0xC7, 0x45, 0xFA, 0x21, 0x00, 0x48, 0xB8, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67,
0x65, 0x20, 0x48, 0xBA, 0x42, 0x6F, 0x78, 0x20, 0x45, 0x78, 0x61, 0x6D, 0x48, 0x89, 0x45, 0xD0,
0x48, 0x89, 0x55, 0xD8, 0xC7, 0x45, 0xE0, 0x70, 0x6C, 0x65, 0x00, 0x48, 0x8D, 0x55, 0xD0, 0x48,
0x8D, 0x45, 0xEE, 0x41, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x49, 0x89, 0xD0, 0x48, 0x89, 0xC2, 0xB9,
0x00, 0x00, 0x00, 0x00, 0x48, 0xB8, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0xFF, 0xD0,
0x89, 0x45, 0xFC, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x48, 0x83, 0xC4, 0x50, 0x5D, 0xC3
};
//此处是要替换的值
unsigned char address[16] = {0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11};
int addressFindFlag=0;
int injectCodeIndex=0;
int indexAddress=0;//记录要替换的地址的最后一位的索引
char addressIndexstrx[3];
char injectCodeIndexstrx[3];
for (int i = 0; i < sizeof(strcode); ++i) {
sprintf(injectCodeIndexstrx,"%02x",strcode[i]);
sprintf(addressIndexstrx,"%02x",address[injectCodeIndex]);
if(strcmp(addressIndexstrx,injectCodeIndexstrx)==0){
addressFindFlag+=1;
injectCodeIndex+=1;
if(addressFindFlag>7){
indexAddress=i;
printf("find:::%d\n",i);
}
}else{
addressFindFlag=0;
injectCodeIndex=0;
}
}
//自身加载一次共享库,防止获取不到MessageBoxA地址
LoadLibraryA("user32.dll");
HMODULE user32 = GetModuleHandle("user32.dll");
FARPROC messagebox = GetProcAddress(user32, "MessageBoxA");
char str1[17];
sprintf(str1,"%p",messagebox);
printf("%s\n",str1);
printf("point:%d",strlen(str1));
unsigned char addressd[16] = {0};
for (int i = 0; i < 8; i++) {
addressd[i] = *((unsigned char*)&messagebox + i);
}
for (int i = 0; i < sizeof(addressd)/2; ++i) {
strcode[indexAddress-sizeof(addressd)/2+i+1]=addressd[i];
}
for (int i = 0; i < sizeof(strcode); i++) {
printf("sssss%d, ",i);
printf("sssss%x\n, ", strcode[i]);
}
printf("Address of MessageBoxA:%d\n",sizeof(addressd));
// 获取目标进程句柄
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 2588);
if (hProcess == NULL) {
printf("打开目标进程失败\n");
return 1;
}
// 在目标进程中分配内存空间
LPVOID lpBaseAddress = VirtualAllocEx(hProcess, NULL, sizeof(strcode), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (lpBaseAddress == NULL) {
printf("在目标进程中分配内存失败\n");
CloseHandle(hProcess);
return 1;
}
// 将机器码写入目标进程中分配的内存空间
if (!WriteProcessMemory(hProcess, lpBaseAddress, strcode, sizeof(strcode), NULL)) {
printf("写入机器码失败\n");
VirtualFreeEx(hProcess, lpBaseAddress, sizeof(strcode), MEM_RELEASE);
CloseHandle(hProcess);
return 1;
}
// 在目标进程中创建一个线程,执行写入的机器码
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpBaseAddress, NULL, 0, NULL);
if (hThread == NULL) {
printf("创建远程线程失败\n");
VirtualFreeEx(hProcess, lpBaseAddress, sizeof(strcode), MEM_RELEASE);
CloseHandle(hProcess);
return 1;
}
// 等待线程执行完毕,并释放相关资源
WaitForSingleObject(hThread, INFINITE);
VirtualFreeEx(hProcess, lpBaseAddress, sizeof(strcode), MEM_RELEASE);
CloseHandle(hThread);
CloseHandle(hProcess);
// MessageBox(NULL, "2", "2", MB_OK);
char * aa[50];
gets(aa);
return 0;
}
这种方式只是一种比较一般的代码注入方式,更有效的是可以使用汇编取到pcb 进程控制块找到kenral.dll找到方法地址,通过这些块可以做到通用的注入代码生成,免杀等。