之前在Android下利用Hook实现mono dll加密里提到了Unity3D研究院之Android加密DLL与破解DLL .SO这篇文章。今天看某个PC上游戏的时候发现用了一样的思路,掏出IDA看了下确实是修改了mono_image_open_from_data_width_name
来实现的。比较好奇有没有简单的方法绕开它而不是去跟汇编较劲,于是找到了一个比较通用的思路。
主要参考了[原创]内存dump 获得基于Unity3d的游戏相关代码 来绕开:mono加载的dll是常驻内存的。所以很简单的两步走:
第一步用到了ProcDump:
第二步就更简单了,使用上文代码处理下导出的数据即可得到一堆dll
char * findDosHeader(char * buffer, int length, int *out_length) { char * pe = NULL; for (int i = 0; i < length - 0x200; i++) { WORD * p = (WORD *)(buffer + i); if (*p != IMAGE_DOS_SIGNATURE) { continue; } IMAGE_NT_HEADERS * ntheader = (IMAGE_NT_HEADERS *)(buffer + 0x80 + i); if (ntheader->Signature != IMAGE_NT_SIGNATURE){ continue; } IMAGE_FILE_HEADER * fileheader = &ntheader->FileHeader; if (!(fileheader->Characteristics & IMAGE_FILE_DLL)){ continue; } IMAGE_SECTION_HEADER * section = IMAGE_FIRST_SECTION(ntheader); int size = 0; for (int j = 0; j < fileheader->NumberOfSections; j++) { if ((section + j)->SizeOfRawData + (section + j)->PointerToRawData > size) { size = (section + j)->SizeOfRawData + (section + j)->PointerToRawData; } } *out_length = size; return (buffer + i); } return NULL; } void find(const char * fileName) { FILE *fp = NULL; fopen_s(&fp, fileName, "rb"); if (fp == NULL) { return; } fseek(fp, 0L, SEEK_END); int length = ftell(fp); fseek(fp, 0L, SEEK_SET); char * pFileBuffer = new char[length]; fread_s(pFileBuffer, length, 1, length, fp); char* ppe = pFileBuffer; int image_length = 0; int buffer_length = length; while (true) { char f[512]; buffer_length -= image_length; ppe = findDosHeader(ppe + image_length, length - (ppe - pFileBuffer) - image_length, &image_length); if (ppe != NULL) { sprintf_s(f, "%s.%x-%x.dll", fileName, ppe, image_length); FILE* outfp = 0; fopen_s(&outfp, f, "wb+"); fwrite(ppe, image_length, 1, outfp); fclose(outfp); printf("%x %x\n", ppe, image_length); } else{ break; } } delete[] pFileBuffer; fclose(fp); }
|
ps. 对安卓上的游戏上文已经说的很清楚了,root过的设备(譬如MuMu)抓取内存即可
pss. 看来还是混淆和IL2CPP靠谱多了(逃