MapFile.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. #include "stdafx.h"
  2. #include "mapfile.h"
  3. CMapFile::CMapFile(char * pPath,bool bWrite,PVOID &pMap,DWORD &dwFileSize)
  4. :pImageView(pMap)
  5. ,dwSize(dwFileSize)
  6. {
  7. this->hFileHandle=INVALID_HANDLE_VALUE;
  8. this->hFileMapHandle=INVALID_HANDLE_VALUE;
  9. this->pImageView =NULL;
  10. this->dwSize =0;
  11. try
  12. {
  13. if(bWrite)
  14. {
  15. this->hFileHandle = CreateFileA(pPath, GENERIC_READ|GENERIC_WRITE,0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL , NULL);
  16. }
  17. else
  18. {
  19. this->hFileHandle = CreateFileA(pPath, GENERIC_READ,0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL , NULL);
  20. }
  21. if(this->hFileHandle==INVALID_HANDLE_VALUE)
  22. {
  23. throw (0);
  24. }
  25. this->dwSize=GetFileSize(this->hFileHandle,NULL);
  26. if(this->dwSize==0)
  27. {
  28. throw (1);
  29. }
  30. if(bWrite)
  31. {
  32. this->hFileMapHandle=CreateFileMappingA(this->hFileHandle,NULL,PAGE_READWRITE,0,0,NULL);
  33. }
  34. else
  35. {
  36. this->hFileMapHandle=CreateFileMappingA(this->hFileHandle,NULL,PAGE_READONLY,0,0,NULL);
  37. }
  38. if(this->hFileMapHandle==INVALID_HANDLE_VALUE)
  39. {
  40. throw (2);
  41. }
  42. CloseHandle(this->hFileHandle);
  43. this->hFileHandle= INVALID_HANDLE_VALUE;
  44. if(bWrite)
  45. {
  46. this->pImageView=MapViewOfFile(this->hFileMapHandle,FILE_MAP_WRITE|FILE_MAP_READ,0,0,0);
  47. }
  48. else
  49. {
  50. this->pImageView=MapViewOfFile(this->hFileMapHandle,FILE_MAP_READ,0,0,0);
  51. }
  52. if(this->pImageView==NULL)
  53. {
  54. throw (4);
  55. }
  56. }
  57. catch(...)
  58. {
  59. this->pImageView=NULL;
  60. }
  61. }
  62. CMapFile::~CMapFile(void)
  63. {
  64. try
  65. {
  66. if(this->pImageView!=NULL)
  67. {
  68. UnmapViewOfFile(this->pImageView);
  69. }
  70. if(this->hFileMapHandle!=INVALID_HANDLE_VALUE)
  71. {
  72. CloseHandle(this->hFileMapHandle);
  73. }
  74. if(this->hFileHandle!=INVALID_HANDLE_VALUE)
  75. {
  76. CloseHandle(this->hFileHandle);
  77. }
  78. }
  79. catch(...)
  80. {
  81. }
  82. }
  83. PIMAGE_SECTION_HEADER
  84. __AddImportTable_GetEnclosingSectionHeader(
  85. DWORD rva,
  86. PIMAGE_NT_HEADERS pNTHeader
  87. )
  88. {
  89. PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNTHeader);
  90. unsigned i;
  91. for ( i=0; i < pNTHeader->FileHeader.NumberOfSections; i++, section++ )
  92. {
  93. // Is the RVA within this section?
  94. if ( (rva >= section->VirtualAddress) &&
  95. (rva < (section->VirtualAddress + section->Misc.VirtualSize)))
  96. return section;
  97. }
  98. return 0;
  99. }
  100. int
  101. AddImportDll(
  102. IN HANDLE hFile,
  103. IN LPSTR lpDllName,
  104. IN DWORD dwBase,
  105. IN PIMAGE_NT_HEADERS pNTHeader
  106. )
  107. {
  108. //
  109. // 通过OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
  110. // 获得导入表的RVA, 利用此RVA找到ImportTable所在的Section,之后计算Offset,公式:
  111. // Offset = (INT)(pSection->VirtualAddress - ->PointerToRawData)
  112. // 之后利用Offset来定位文件中ImportTable的位置.pSection
  113. //
  114. PIMAGE_IMPORT_DESCRIPTOR pImportDesc = 0;
  115. PIMAGE_SECTION_HEADER pSection = 0;
  116. PIMAGE_THUNK_DATA pThunk, pThunkIAT = 0;
  117. int Offset = -1;
  118. pSection = __AddImportTable_GetEnclosingSectionHeader(
  119. pNTHeader->OptionalHeader.DataDirectory
  120. [IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress,
  121. pNTHeader);
  122. if(!pSection)
  123. {
  124. fprintf(stderr, "没找到导入表。我日..\n");
  125. return -1;
  126. }
  127. Offset = (int) (pSection->VirtualAddress - pSection->PointerToRawData);
  128. //
  129. // 计算ImportTable在文件中的位置
  130. //
  131. pImportDesc =(PIMAGE_IMPORT_DESCRIPTOR)(pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress - Offset + dwBase);
  132. // 取出导入的DLL的个数 ,有问题暂时保留 ---2012-11-20
  133. //int nImportDllCount = 0;
  134. //while(1)
  135. //{
  136. // if ((pImportDesc->TimeDateStamp==0 ) && (pImportDesc->Name==0))
  137. // break;
  138. // pThunk = (PIMAGE_THUNK_DATA)(pImportDesc->Characteristics);
  139. // pThunkIAT = (PIMAGE_THUNK_DATA)(pImportDesc->FirstThunk);
  140. // if(pThunk == 0 && pThunkIAT == 0)
  141. // return -1;
  142. // nImportDllCount++;
  143. // pImportDesc++;
  144. //}
  145. ////
  146. //// 恢复pImportDesc的值,方便下面的复制当前导入表的操作.
  147. ////
  148. //pImportDesc -= nImportDllCount;
  149. // 取出导入的DLL的个数 ,有问题暂时保留---2012-11-20
  150. int nImportDllCount = 5;//我们输入法导入DLL个数为5个
  151. //
  152. // 取得ImportTable所在Section的RawData在文件中的末尾地址,计算公式:
  153. // dwOrigEndOfRawDataAddr = pSection->PointerToRawData + pSection->Misc.VirtualSize
  154. //
  155. DWORD dwEndOfRawDataAddr = pSection->PointerToRawData + pSection->Misc.VirtualSize;
  156. PIMAGE_IMPORT_DESCRIPTOR pImportDescVector =
  157. (PIMAGE_IMPORT_DESCRIPTOR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 20 * (nImportDllCount+1));
  158. if(pImportDescVector == NULL)
  159. {
  160. //fprintf(stderr, "分配内存失败. --错误号: %d\n", GetLastError());
  161. return -1;
  162. }
  163. CopyMemory(pImportDescVector+1, pImportDesc, 20*nImportDllCount);
  164. //
  165. // 构造添加数据的结构
  166. //
  167. struct _Add_Data
  168. {
  169. char szDllName[MAX_PATH]; // 导入DLL的名字
  170. int nDllNameLen; // 实际填充的名字的长度
  171. WORD Hint; // 导入函数的Hint
  172. char szFuncName[MAX_PATH]; // 导入函数的名字
  173. int nFuncNameLen; // 导入函数名字的实际长度
  174. int nTotal; // 填充的总长度
  175. } Add_Data;
  176. memset(Add_Data.szDllName,0,MAX_PATH);
  177. memset(Add_Data.szFuncName,0,MAX_PATH);
  178. strcpy(Add_Data.szDllName, lpDllName);
  179. strcpy(Add_Data.szFuncName, "CBFunA");
  180. //
  181. // +1表示&#39;\0&#39;字符
  182. //
  183. Add_Data.nDllNameLen = strlen(Add_Data.szDllName) + 1;
  184. Add_Data.nFuncNameLen = strlen(Add_Data.szFuncName) + 1;
  185. Add_Data.Hint = 0;
  186. //
  187. // 计算总的填充字节数
  188. //
  189. Add_Data.nTotal = Add_Data.nDllNameLen + sizeof(WORD) + Add_Data.nFuncNameLen;
  190. //
  191. // 检查ImportTable所在的Section中的剩余空间是否能够容纳新的ImportTable.
  192. // 未对齐前RawData所占用的空间存放在pSection->VirtualSize中,用此值加上新的ImportTable长度与
  193. // 原长度进行比较.
  194. //
  195. // nTotalLen 为新添加内容的总长度
  196. // Add_Data.nTotal 为添加的DLL名称,Hint与导入函数的名字的总长度.
  197. // 8 为IMAGE_IMPORT_BY_NAME结构的长度.
  198. // 20*(nImportDllCount+1) 为新的ImportTable的长度.
  199. //
  200. int nTotalLen = Add_Data.nTotal + 8 + 20*(nImportDllCount+1);
  201. // printf("TotalLen: %d byte(s)\n", nTotalLen);
  202. if(pSection->Misc.VirtualSize + nTotalLen > pSection->SizeOfRawData)
  203. {
  204. return -1;
  205. }
  206. IMAGE_IMPORT_DESCRIPTOR Add_ImportDesc;
  207. //
  208. // ThunkData结构的地址
  209. //
  210. Add_ImportDesc.Characteristics = dwEndOfRawDataAddr + Add_Data.nTotal + Offset;
  211. Add_ImportDesc.TimeDateStamp = -1;
  212. Add_ImportDesc.ForwarderChain = -1;
  213. //
  214. // DLL名字的RVA
  215. //
  216. Add_ImportDesc.Name = dwEndOfRawDataAddr + Offset;
  217. Add_ImportDesc.FirstThunk = Add_ImportDesc.Characteristics;
  218. CopyMemory(pImportDescVector, &Add_ImportDesc, 20);
  219. //
  220. // 对文件进行修改
  221. //
  222. DWORD dwBytesWritten = 0;
  223. DWORD dwBuffer = dwEndOfRawDataAddr + Offset + Add_Data.nTotal + 8;
  224. long lDistanceToMove = (long)&(pNTHeader->OptionalHeader.DataDirectory
  225. [IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress) - dwBase;
  226. int nRet =0;
  227. //
  228. // 修改IMAGE_DIRECTOR_ENTRY_IMPORT中VirtualAddress的地址,
  229. // 使其指向新的导入表的位置
  230. //
  231. SetFilePointer(hFile, lDistanceToMove, NULL, FILE_BEGIN);
  232. // printf("OrigEntryImport: %x\n", pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
  233. nRet = WriteFile(hFile, (PVOID)&dwBuffer, 4, &dwBytesWritten, NULL);
  234. if(!nRet)
  235. {
  236. //fprintf(stderr, "写 导入表地址的时候失败了耶. --错误号: %d\n", GetLastError());
  237. return -1;
  238. }
  239. // printf("NewEntryImport: %x\n", pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
  240. //
  241. // 修改导入表长度
  242. //
  243. dwBuffer = pNTHeader->OptionalHeader.DataDirectory
  244. [IMAGE_DIRECTORY_ENTRY_IMPORT].Size + 40;
  245. nRet = WriteFile(hFile, (PVOID)&dwBuffer, 4, &dwBytesWritten, NULL);
  246. if(!nRet)
  247. {
  248. //fprintf(stderr, "写 导入表大小的的时候失败了耶. --错误号: %d\n", GetLastError());
  249. return -1;
  250. }
  251. //
  252. // 修改[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT]中VirtualAddress和Size成员,设置为0
  253. //
  254. lDistanceToMove = (long)&(pNTHeader->OptionalHeader.DataDirectory
  255. [IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress) - dwBase;
  256. dwBuffer = 0;
  257. SetFilePointer(hFile, lDistanceToMove, NULL, FILE_BEGIN);
  258. WriteFile(hFile, (PVOID)&dwBuffer, 4, &dwBytesWritten, NULL);
  259. WriteFile(hFile, (PVOID)&dwBuffer, 4, &dwBytesWritten, NULL);
  260. //
  261. // 修改ImportTable所在节的长度
  262. //
  263. lDistanceToMove = (long)&(pSection->Misc.VirtualSize) - dwBase;
  264. SetFilePointer(hFile, lDistanceToMove, NULL, FILE_BEGIN);
  265. dwBuffer = pSection->Misc.VirtualSize + nTotalLen;
  266. nRet = WriteFile(hFile, (PVOID)&dwBuffer, 4, &dwBytesWritten, NULL);
  267. if(!nRet)
  268. {
  269. //fprintf(stderr, "重写导入表地址的时候失败了耶. --错误号: %d\n", GetLastError());
  270. return -1;
  271. }
  272. //
  273. // 修改SECTION的Characteristics属性修改为E0000020
  274. //
  275. lDistanceToMove = (long)&(pSection->Characteristics) - dwBase;
  276. dwBuffer = 0xE0000020;
  277. SetFilePointer(hFile, lDistanceToMove, NULL, FILE_BEGIN);
  278. nRet = WriteFile(hFile, (PVOID)&dwBuffer, 4, &dwBytesWritten, NULL);
  279. if(!nRet)
  280. {
  281. //fprintf(stderr, "写E0000020的时候失败了耶. --错误号: %d\n", GetLastError());
  282. return -1;
  283. }
  284. //
  285. // 从节的末尾添加新的DLL内容
  286. //
  287. lDistanceToMove = dwEndOfRawDataAddr;
  288. SetFilePointer(hFile, lDistanceToMove, NULL, FILE_BEGIN);
  289. nRet = WriteFile(hFile, Add_Data.szDllName, Add_Data.nDllNameLen, &dwBytesWritten, NULL);
  290. nRet = WriteFile(hFile, (LPVOID)&(Add_Data.Hint), sizeof(WORD), &dwBytesWritten, NULL);
  291. nRet = WriteFile(hFile, Add_Data.szFuncName, Add_Data.nFuncNameLen, &dwBytesWritten, NULL);
  292. dwBuffer = dwEndOfRawDataAddr + Add_Data.nDllNameLen + Offset;
  293. nRet = WriteFile(hFile, (LPVOID)&dwBuffer, 4, &dwBytesWritten, NULL);
  294. dwBuffer = 0;
  295. nRet = WriteFile(hFile, (LPVOID)&dwBuffer, 4, &dwBytesWritten, NULL);
  296. nRet = WriteFile(hFile, (LPVOID)pImportDescVector, 20*(nImportDllCount+1), &dwBytesWritten, NULL);
  297. HeapFree(GetProcessHeap(), 0, pImportDescVector);
  298. return 0;
  299. }
  300. LPVOID HookIMEdllIAT(char *SouceMode,char* hookdll)
  301. {
  302. DWORD dwFileSize =0 ;
  303. LPVOID pPeImage=NULL;
  304. CMapFile cMapFile(SouceMode,true,pPeImage,dwFileSize);
  305. if(pPeImage!=NULL)
  306. {
  307. BYTE *pFileImage = (BYTE*)pPeImage;
  308. PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pFileImage;
  309. PIMAGE_FILE_HEADER pFileHeader =(PIMAGE_FILE_HEADER)(pFileImage+pDosHeader->e_lfanew+4);
  310. PIMAGE_OPTIONAL_HEADER32 pOptionalHeader =(PIMAGE_OPTIONAL_HEADER32)(pFileImage+pDosHeader->e_lfanew+4+sizeof(IMAGE_FILE_HEADER));
  311. PIMAGE_NT_HEADERS pNTHeader=(PIMAGE_NT_HEADERS)&((const unsigned char *)(pFileImage))[pDosHeader->e_lfanew];
  312. //这里加了以共享读写模式打开文件,解决文件未关闭时,打开文件报错的问题。
  313. HANDLE handle = CreateFileA(SouceMode,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
  314. AddImportDll(handle,hookdll,(DWORD)pFileImage,pNTHeader);
  315. CloseHandle(handle);
  316. }
  317. return pPeImage;
  318. }