原文:https://www.pediy.com/kssd/pediy11/104318.html
【文章标题】: 菜鸟第一次DIY, 为你的软件加载皮肤
【文章作者】: blueapplez
【作者邮箱】: blueapple1987@163.com
【软件名称】: War3 改键工具 1.02
【下载地址】: 附件
【操作平台】: Windows XP SP2
【完成时间】:2010-1-2 2:58:11
【文章链接】:http://bbs.pediy.com/showthread.php?p=737611
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
今晚刚修改了不久之前做的一个 War3 改键工具,看了安静a 发的一篇求助帖《如何给一个写好的软件加个皮肤!》,后来有人回复说加载一些开源的皮肤库就行了,于是我就动手DIY我的刚完成的小作品了!
【详细过程】
(一) 找到一个Appface的一个开源库,查了一下里面的调用过程,以前我用的时候是用静态库这样用
SkinStart(_T("Skin\\sap_af.urf"),WINDOW_TYPE_VC,"",GTP_LOAD_FILE,NULL,NULL);
typedef BOOL (__stdcall *APPFACE_START)(char*,int,char*,int,DWORD,char*) ; HMODULE hDll = LoadLibrary("1.dll"); if (hDll != NULL) { APPFACE_START fun = (APPFACE_START)GetProcAddress(hDll, "SkinStart"); if (fun != NULL) { fun(_T("1.urf"),1,"",1,NULL,NULL); } }
//Get the alignment Address DWORD Alignment(DWORD dwValue, DWORD dwDuiQ) { while(dwValue % dwDuiQ != 0) { dwValue++; } return dwValue; } //Modify the PE file, include Add new Section and sth else DWORD SetPeInfo(void *ImageOfPe, DWORD dwFileSize, DWORD dwOffset) { WORD NumOfSection=0; DWORD RawOfEntryPoint=0; DWORD AddressOfEntryPoint=0; PIMAGE_DOS_HEADER pDosHead=NULL; PIMAGE_NT_HEADERS pNtHead=NULL; PIMAGE_SECTION_HEADER pSectionHead=NULL; pDosHead=(PIMAGE_DOS_HEADER)ImageOfPe; pNtHead=(PIMAGE_NT_HEADERS)((unsigned char *)pDosHead+pDosHead->e_lfanew); //Record the old PE EnterPoint, we will modify it later. AddressOfEntryPoint=pNtHead->OptionalHeader.AddressOfEntryPoint; //Record the number of the section segment, we will modify it later. NumOfSection=pNtHead->FileHeader.NumberOfSections; //the first section's address pSectionHead=(PIMAGE_SECTION_HEADER)((unsigned char *)pNtHead+ sizeof(pNtHead->Signature)+sizeof(IMAGE_FILE_HEADER)+ pNtHead->FileHeader.SizeOfOptionalHeader); //Get The Last Section Pointer PIMAGE_SECTION_HEADER pLastSection = (IMAGE_SECTION_HEADER *)((DWORD)pSectionHead + sizeof(IMAGE_SECTION_HEADER)*(NumOfSection-1)); IMAGE_SECTION_HEADER imageSectionInsert; memset(&imageSectionInsert, 0, sizeof(IMAGE_SECTION_HEADER)); //Write sth to the new Section //set a name for the new section memcpy(imageSectionInsert.Name, ".blue", sizeof(".blue")); imageSectionInsert.Misc.VirtualSize = 0x200; imageSectionInsert.VirtualAddress = Alignment(pLastSection->VirtualAddress + pLastSection->Misc.VirtualSize, 0x1000); imageSectionInsert.SizeOfRawData = 0x200; imageSectionInsert.PointerToRawData = dwFileSize + dwOffset; //Set Characteristics to read write and execute. imageSectionInsert.Characteristics = IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE ; //the add 1, in fact add a sizeof IMAGE_SECTION_HEADER memcpy(pLastSection + 1, &imageSectionInsert, sizeof(IMAGE_SECTION_HEADER)); //1.Modify the PE Entrypoint pNtHead->OptionalHeader.AddressOfEntryPoint = imageSectionInsert.VirtualAddress; //2.Add the number of section segment pNtHead->FileHeader.NumberOfSections++; //3.Add 0x200 to SizeofImage pNtHead->OptionalHeader.SizeOfImage += 0x200; //4.Add 0x200 to SizeOfCode pNtHead->OptionalHeader.SizeOfCode += 0x200; //5.Add 0x200 to SizeOfInitialishedData pNtHead->OptionalHeader.SizeOfInitializedData += 0x200; //return the new EntryPoint and the ImageBase. return AddressOfEntryPoint + pNtHead->OptionalHeader.ImageBase; } void CMyDlg::OnOK() { DWORD dwFileSize = 0; HANDLE hFile = ::CreateFile("a.exe", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (hFile == INVALID_HANDLE_VALUE) { return ; } dwFileSize = GetFileSize(hFile, NULL); if (dwFileSize == 0) { return; } char *szpPE = new char [dwFileSize]; memset (szpPE, 0, dwFileSize); DWORD dwRead = 0; ReadFile(hFile, szpPE, dwFileSize, &dwRead, NULL); if (dwRead != dwFileSize) { return ; } CloseHandle(hFile); //Set PE Info DWORD dwOffset = Alignment(dwFileSize, 0x200) - dwFileSize; DWORD dwEnterLastPoint = SetPeInfo(szpPE, dwFileSize, dwOffset); //Add 200 Bytes and create a new file hFile = ::CreateFile("b.exe", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (hFile == INVALID_HANDLE_VALUE) { return ; } BYTE *sz200Size = new BYTE[0x200 + dwOffset]; memset(sz200Size, 0, 0x200+dwOffset); // Write binary codes here, but do not forget jmp to the old EntryPoint. // sz200Size[dwOffset] = 0xe9; // sz200Size[dwOffset+1] = 0xbb; // sz200Size[dwOffset+2] = 0x7b; // sz200Size[dwOffset+3] = 0xFF; // sz200Size[dwOffset+4] = 0xFF; //set the file size SetFilePointer(hFile, dwFileSize + dwOffset + 0x200, NULL, FILE_BEGIN); //set file to the start position SetFilePointer(hFile, NULL, NULL, FILE_BEGIN); DWORD dwFeiWu = 0; //write modified szpPE info to new file. WriteFile(hFile, szpPE, dwFileSize, &dwFeiWu, NULL); //write the 0x200 section code to new file, do not forget the offset file size. WriteFile(hFile, sz200Size, dwOffset + 0x200, &dwFeiWu, NULL); CloseHandle(hFile); //release the memory we used. delete [] sz200Size; delete [] szpPE; }
00436000 > 60 pushad ; 这是新增Section段的开始 00436001 68 36604300 push 00436036 ; ASCII "1.dll" 00436006 E8 70BD3C7C call kernel32.LoadLibraryA 0043600B 68 3D604300 push 0043603D ; ASCII "SkinStart" 00436010 50 push eax 00436011 E8 1A4E3D7C call kernel32.GetProcAddress 00436016 6A 00 push 0 00436018 6A 00 push 0 0043601A 6A 01 push 1 0043601C 68 58604300 push 00436058 ; 这个地方我也没搞懂 00436021 6A 01 push 1 00436023 68 48604300 push 00436048 ; ASCII "1.urf" 00436028 FFD0 call eax 0043602A 61 popad 0043602B - E9 6247FDFF jmp 0040A792 ; 跳到原来的入口点执行 00436030 0000 add byte ptr [eax], al 00436032 0000 add byte ptr [eax], al 00436034 0000 add byte ptr [eax], al 00436036 312E xor dword ptr [esi], ebp ; 字符串 1.dll 00436038 64:6C ins byte ptr es:[edi], dx 0043603A 6C ins byte ptr es:[edi], dx 0043603B 0000 add byte ptr [eax], al 0043603D 53 push ebx ; 字符串 SkinStart 0043603E 6B69 6E 53 imul ebp, dword ptr [ecx+6E], 53 00436042 74 61 je short 004360A5 00436044 72 74 jb short 004360BA 00436046 0000 add byte ptr [eax], al 00436048 312E xor dword ptr [esi], ebp ; 字符串 1.urf 0043604A 75 72 jnz short 004360BE 0043604C 66:0000 add byte ptr [eax], al 0043604F 0000 add byte ptr [eax], al 00436051 0000 add byte ptr [eax], al 00436053 0000 add byte ptr [eax], al 00436055 0000 add byte ptr [eax], al 00436057 0000 add byte ptr [eax], al 00436059 0000 add byte ptr [eax], al