したらばTOP ■掲示板に戻る■ 全部 1-100 最新50 | メール | |

管理人の独り言(プログラミング関連)

1みみず★:2008/08/10(日) 23:28:15
あまりにもプログラミングの内容が増えすぎた。
よって隔離スレの中を更に隔離。

1115774さん:2008/12/17(水) 23:41:29 ID:CENbthlg0
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <functional>

#include <windows.h>
#include <tchar.h>

#if defined(UNICODE) || defined(_UNICODE)
#error UNICODE版はサポートしてないみたいです。
#endif
#if defined(_WIN64)
#error 64bit版はサポートしてないみたいです。
#endif

#define RVA(po, rva) \
((void *)(((BYTE *)(po)) + ((long)(rva))))

IMAGE_SECTION_HEADER *GetTextSection(IMAGE_SECTION_HEADER *section, WORD numOfSection){
for(int i = 0; i < numOfSection; ++i){
if(lstrcmpA((char *)section[i].Name, ".text") == 0){
return &section[i];
}
}
return NULL;
}

1116774さん:2008/12/17(水) 23:42:02 ID:CENbthlg0
void Unko(void *src, void *des, DWORD srcSize, DWORD desSize){
IMAGE_DOS_HEADER *pSrcDosHeader = (IMAGE_DOS_HEADER *)src;
IMAGE_DOS_HEADER *pDesDosHeader = (IMAGE_DOS_HEADER *)des;

if(pSrcDosHeader->e_magic == IMAGE_DOS_SIGNATURE && pDesDosHeader->e_magic == IMAGE_DOS_SIGNATURE){
IMAGE_NT_HEADERS32 *pSrcNtHeader = (IMAGE_NT_HEADERS32 *)RVA(src, pSrcDosHeader->e_lfanew);
IMAGE_NT_HEADERS32 *pDesNtHeader = (IMAGE_NT_HEADERS32 *)RVA(des, pDesDosHeader->e_lfanew);

if(pSrcNtHeader->Signature == IMAGE_NT_SIGNATURE && pDesNtHeader->Signature == IMAGE_NT_SIGNATURE){
WORD srcNumberOfSections = pSrcNtHeader->FileHeader.NumberOfSections;
WORD desNumberOfSections = pDesNtHeader->FileHeader.NumberOfSections;

IMAGE_SECTION_HEADER *pSrcSections = IMAGE_FIRST_SECTION(pSrcNtHeader);
IMAGE_SECTION_HEADER *pDesSections = IMAGE_FIRST_SECTION(pDesNtHeader);

IMAGE_SECTION_HEADER *pSrcTextSection = GetTextSection(pSrcSections, srcNumberOfSections);
IMAGE_SECTION_HEADER *pDesTextSection = GetTextSection(pDesSections, desNumberOfSections);

if(pSrcTextSection && pDesTextSection){
//ソースの.textセクションの大きさ
DWORD srcTextSectionSize = pSrcTextSection->SizeOfRawData;

//挿入先の.textセクションのファイル上の大きさ
DWORD desTextSectionSize = pDesTextSection->SizeOfRawData;
//挿入先の.textセクションのメモリ上の大きさ
DWORD desTextSectionVirtualSize = pDesTextSection->Misc.VirtualSize;

//挿入先のセクションのアラインメントの大きさ
DWORD desSectionAlignment = pDesNtHeader->OptionalHeader.SectionAlignment;
//挿入先のセクションのファイル上のアラインメントの大きさ
DWORD desFileAlignment = pDesNtHeader->OptionalHeader.FileAlignment;

//挿入後の.textセクションのファイル上の大きさ(もっと良い求め方があったが、忘れた。)幾らか足しているのはアセンブリ用(下の方のcode分)
DWORD desAfterTextSectionSize = ((srcTextSectionSize + desTextSectionSize) + desFileAlignment - 1 + 10 /*アセンブリ分*/) / desFileAlignment * desFileAlignment;
//.textセクションのファイル上の増加量
DWORD desTextSectionAddition = desAfterTextSectionSize - desTextSectionSize;
//挿入後の.textセクションのメモリ上の大きさ?良く分からん。
//DWORD desAfterTextSectionVirtualSize = (desAfterTextSectionSize + desSectionAlignment - 1) / desSectionAlignment * desSectionAlignment;
DWORD desAfterTextSectionVirtualSize = desTextSectionVirtualSize + desTextSectionAddition;

//挿入後のexeの大きさ
SIZE_T fileSize
= desSize //元のファイルの大きさ
+ desTextSectionAddition //増えた.textセクションの大きさ
;

void *p = VirtualAlloc(NULL, fileSize, MEM_COMMIT, PAGE_READWRITE);

1117774さん:2008/12/17(水) 23:42:25 ID:CENbthlg0
if(p){
#define DESTOP(po) (void *)((long)(po) - (long)(des) + (long)(p))
memcpy(p, des, desSize);
//TODO
//.textセクションの挿入&エントリポイントの変更&アセンブリ(バイナリ)の挿入&情報の修正

IMAGE_NT_HEADERS32 *pImageNtHeader = (IMAGE_NT_HEADERS32 *)DESTOP(pDesNtHeader);

IMAGE_SECTION_HEADER *pImageSections = (IMAGE_SECTION_HEADER *)DESTOP(pDesSections);
IMAGE_SECTION_HEADER *pTextSection = (IMAGE_SECTION_HEADER *)DESTOP(pDesTextSection);

//.textセクションより後ろにあるものを移動&値変更
{
//.textセクションの開始位置(RVA)
DWORD pTextSectionPointerToRawData = pTextSection->PointerToRawData;
std::priority_queue<std::pair<DWORD, IMAGE_SECTION_HEADER *>, std::vector<std::pair<DWORD, IMAGE_SECTION_HEADER *> >, std::greater<std::vector<std::pair<DWORD, IMAGE_SECTION_HEADER *> >::value_type > > q;
for(int i = 0; i < desNumberOfSections; ++i){
if(pImageSections[i].PointerToRawData > pTextSectionPointerToRawData){
q.push(std::pair<DWORD, IMAGE_SECTION_HEADER *>(pImageSections[i].PointerToRawData, &pImageSections[i]));
pImageSections[i].PointerToRawData += desTextSectionAddition;
}
}

while(!q.empty()){
std::pair<DWORD, IMAGE_SECTION_HEADER *> &top = q.top();
void *sp = RVA(p, top.first);
memmove(RVA(sp, desTextSectionAddition), sp, top.second->SizeOfRawData);

q.pop();
}
}

//.textセクションを弄くる
{
void *sp = RVA(p, pTextSection->PointerToRawData);
memmove(RVA(sp, desTextSectionAddition), sp, pTextSection->SizeOfRawData);
static const BYTE code[] = {
0xE8, 0x00, 0x00, 0x00, 0x00, //CALL rel32
0xE9, 0x00, 0x00, 0x00, 0x00, //JMP rel32
};

memcpy(sp, code, sizeof(code));
memcpy(RVA(sp, sizeof(code)), RVA(src, pSrcTextSection->PointerToRawData), pSrcTextSection->SizeOfRawData);

//挿入元のEXEのエントリポイントの.textでの相対位置
DWORD srcEntryPoint = pSrcNtHeader->OptionalHeader.AddressOfEntryPoint - pSrcNtHeader->OptionalHeader.BaseOfCode;
//挿入先のEXEのエントリポイントの.textでの相対位置
DWORD desEntryPoint = pDesNtHeader->OptionalHeader.AddressOfEntryPoint - pDesNtHeader->OptionalHeader.BaseOfCode;

pImageNtHeader->OptionalHeader.AddressOfEntryPoint = pImageNtHeader->OptionalHeader.BaseOfCode;
*((DWORD *)RVA(sp, 1)) = sizeof(code) - 5 + srcEntryPoint;
*((DWORD *)RVA(sp, 6)) = desTextSectionAddition + desEntryPoint - 10;
}

//.textセクションの大きさの修正
{
pTextSection->SizeOfRawData = desAfterTextSectionSize;
pTextSection->Misc.VirtualSize = desAfterTextSectionVirtualSize;
}

FILE *filew = fopen("out.exe", "wb");
fwrite(p, fileSize, 1, filew);
VirtualFree(p, fileSize, MEM_DECOMMIT);
}
}
}
}
}

1118774さん:2008/12/17(水) 23:42:35 ID:CENbthlg0

int main(int argc, char **argv){
if(argc < 4){
std::cerr << "引数が少ないみたいです。" << std::endl;
std::cerr << "コマンド S D T" << std::endl;
return -1;
}
HANDLE hSrc = CreateFileA(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
HANDLE hDes = CreateFileA(argv[2], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hSrc != INVALID_HANDLE_VALUE && hDes != INVALID_HANDLE_VALUE){
LARGE_INTEGER srcSize, desSize;
if(GetFileSizeEx(hSrc, &srcSize) && GetFileSizeEx(hDes, &desSize)){
std::cout << "FROM:" << srcSize.QuadPart << "bytes" << std::endl;
std::cout << " TO :" << desSize.QuadPart << "bytes" << std::endl;

//でかすぎるのはここで一応切っておく。これより小さくても本当はやめるべきだが。
if(!srcSize.HighPart && !desSize.HighPart){
HANDLE hSrcMap = CreateFileMappingA(hSrc, NULL, PAGE_READONLY, 0, 0, NULL);
HANDLE hDesMap = CreateFileMappingA(hDes, NULL, PAGE_READONLY, 0, 0, NULL);
if(hSrcMap && hDesMap){
void *pSrc = MapViewOfFile(hSrcMap, FILE_MAP_READ, 0, 0, 0);
void *pDes = MapViewOfFile(hDesMap, FILE_MAP_READ, 0, 0, 0);
if(pSrc && pDes){
Unko(pSrc, pDes, srcSize.LowPart, desSize.LowPart);
}
if(pSrc)
UnmapViewOfFile(pSrc);
if(pDes)
UnmapViewOfFile(pDes);
}
if(hSrcMap)
CloseHandle(hSrcMap);
if(hDesMap)
CloseHandle(hDesMap);
}
}
}
if(hSrc != INVALID_HANDLE_VALUE)
CloseHandle(hSrc);
if(hDes != INVALID_HANDLE_VALUE)
CloseHandle(hDes);
}


新着レスの表示


名前: E-mail(省略可)

※書き込む際の注意事項はこちら

※画像アップローダーはこちら

(画像を表示できるのは「画像リンクのサムネイル表示」がオンの掲示板に限ります)

掲示板管理者へ連絡 無料レンタル掲示板