目录
1.简单的混淆代码
2.恶意软件资源中释放混淆资源
3.逆向分析
4.参考
简单的混淆代码
在恶意软件分析中,混淆是经常使用的一种手段。恶意软件通过对数据进行混淆,不但给杀毒软件的检测和查杀带来一定的困难,也会给逆向分析者带来一定的阻碍。这里就抛出一个非常简单的砖来说说混淆。我这里简单的写了一个程序,输入想要混淆的文件名就会在同目录下生成名为shellcode的混淆文件。这里混淆过程其实也非常简单,就是对文件进行读写异或等操作
1 #include2 #include 3 #include 4 5 void __cdecl _tmain(int argc, TCHAR *argv[]) 6 { 7 HANDLE hFiler; 8 HANDLE hFilew; 9 BOOL ifFilesize = FALSE;10 BOOL bErrorFlag = FALSE;11 BOOL Flag = FALSE;12 DWORD buffertoread;13 DWORD dwByteWrite = 0;14 LPVOID lpAddress;15 LARGE_INTEGER FileSize;16 17 //获取文件句柄18 hFiler = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);19 if (hFiler == INVALID_HANDLE_VALUE)20 {21 printf("Unable to open file!");22 return;23 }24 //获取文件大小25 ifFilesize = GetFileSizeEx(hFiler, &FileSize);26 if (ifFilesize == FALSE)27 {28 printf("%d", GetLastError());29 }30 else31 {32 printf("%lld", FileSize.QuadPart);33 }34 35 //分配一块内存36 lpAddress = VirtualAlloc(NULL, (SIZE_T)FileSize.QuadPart, MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE);37 if (lpAddress == NULL)38 {39 printf("LocalAlloc failed!");40 return;41 }42 43 //读取文件44 bErrorFlag = ReadFile(hFiler, lpAddress, (DWORD)FileSize.QuadPart, &buffertoread, NULL);45 if (bErrorFlag == FALSE)46 {47 printf("Readfile false:%d", GetLastError());48 return;49 }50 51 //对数据进行异或,最简单的混淆,可以修改这里来实现更加复杂的混淆52 BYTE *point = lpAddress;53 for (int i = 0; i < (int)FileSize.QuadPart; i++)54 {55 (*point) ^= 0x99;56 point++;57 }58 59 //在同目录下生成一个名为shellcode的文件60 hFilew = CreateFile(L"shellcode", GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);61 if (hFilew == INVALID_HANDLE_VALUE)62 {63 printf("Unable to open file");64 }65 66 //写入混淆后的内容67 Flag = WriteFile(hFilew, lpAddress, (DWORD)FileSize.QuadPart, &dwByteWrite, NULL);68 if (Flag == FALSE)69 {70 printf("Fail to WriteFile");71 }72 73 return;74 }
恶意软件资源中释放混淆代码
上面说到的是混淆的过程,这里就是恶意软件对资源混淆后是如何进行释放的。这里释放资源和第二课释放资源类似,不过由于资源混淆了,所以多了一步解密资源的过程。由于资源在PE中为只读数据,所以获取到指向资源的指针后不能像第二课那样直接进行解密,需要复制到内存中再进行解密。还有就是我们之前加混淆是异或0x99,所以解密也是通过异或0x99(这里可以不懂可以看一下关于异或的知识)。
1 #include2 #include 3 4 #include"resource.h" //要包含资源文件的头文件 5 6 int main() 7 { 8 HRSRC Shellcode; 9 HGLOBAL Loadshellcode;10 HANDLE hFile;11 DWORD ShellcodeSize;12 DWORD dwByteWrite = 0;13 LPVOID Lockshellcode;14 LPVOID lpAddress;15 BOOL Flag = FALSE;16 17 //找到资源18 Shellcode = FindResource(NULL, MAKEINTRESOURCE(IDR_SHELLCODE1), TEXT("Shellcode"));19 if (Shellcode == NULL)20 {21 printf("Could not locate dialog box.");22 return 0;23 }24 25 //加载资源26 Loadshellcode = LoadResource(NULL, Shellcode);27 if (Loadshellcode == NULL)28 {29 printf("Could not lock dialog box.");30 return 0;31 }32 33 //获取指向资源的指针34 Lockshellcode = LockResource(Loadshellcode);35 if (Lockshellcode == NULL)36 {37 printf("Could not lock dialog box.");38 return 0;39 }40 41 //获取资源大小,用于下面写文件42 ShellcodeSize = SizeofResource(NULL, Shellcode);43 44 //资源处为只读数据不能直接进行解密,需要复制到内存空间中才可以进行解密45 lpAddress = VirtualAlloc(NULL, (SIZE_T)ShellcodeSize, MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE);46 if (lpAddress == NULL)47 {48 printf("LocalAlloc failed!");49 return 0;50 }51 52 //复制资源到内存空间53 memcpy(lpAddress, Lockshellcode, (size_t)ShellcodeSize);54 55 //解密出shellcode56 byte *point = lpAddress;57 for (int i = 0; i < (int)ShellcodeSize; i++)58 {59 (*point) ^= 0x99;60 point++;61 }62 63 //创建文件64 hFile = CreateFile(L"PE", GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);65 if (hFile == INVALID_HANDLE_VALUE)66 {67 printf("Unable to open file");68 }69 70 //写入文件71 Flag = WriteFile(hFile, lpAddress, ShellcodeSize, &dwByteWrite, NULL);72 if (Flag == FALSE)73 {74 printf("Fail to WriteFile");75 }76 77 return 0;78 }
逆向分析
逆向分析时,如果资源经过混淆,我们用resourse hacker提取出来是混淆后的数据,如果再写一个解密程序进行解密是非常耗时间的(可以通过逆向恶意程序解密资源的过程来编写解密程序)。由于恶意程序最终需要的也是解密后的数据,所以我们可以通过OD跟踪恶意程序解密出资源数据后,再转存解密后的数据。如何确定那个地方是数据解密后呢?我们从上面释放资源的程序中看出,由于需要解密一块数据,所以会进入一个循环对数据进行解密。当循环结束时,我们就可以认为数据解密完成。在平时的恶意软件分析中,数据解密也会进入循环中,有经验的逆向分析者可能一眼就看出数据解密的地方。对初学者来说多分析多调试,也会很快会找到其中的规律
参考
文件读写:https://docs.microsoft.com/zh-cn/windows/desktop/FileIO/opening-a-file-for-reading-or-writing
获取文件大小:https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfilesize
内存操作:https://docs.microsoft.com/zh-cn/windows/desktop/Memory/reserving-and-committing-memory