标签:初学者 resource font failed address div 释放 加载 turn
1.简单的混淆代码
2.恶意软件资源中释放混淆资源
3.逆向分析
4.参考
在恶意软件分析中,混淆是经常使用的一种手段。恶意软件通过对数据进行混淆,不但给杀毒软件的检测和查杀带来一定的困难,也会给逆向分析者带来一定的阻碍。这里就抛出一个非常简单的砖来说说混淆。我这里简单的写了一个程序,输入想要混淆的文件名就会在同目录下生成名为shellcode的混淆文件。这里混淆过程其实也非常简单,就是对文件进行读写异或等操作
1 #include<Windows.h> 2 #include<stdio.h> 3 #include<tchar.h> 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 else 31 { 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 #include<Windows.h> 2 #include<stdio.h> 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 //解密出shellcode 56 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
标签:初学者 resource font failed address div 释放 加载 turn
原文地址:https://www.cnblogs.com/QKSword/p/10549784.html