能力值:
( LV2,RANK:10 )
|
-
-
2 楼
ImageBase -> NewImageBase 需要重定位的地址 - OldImageBase + NewImageBase
|
能力值:
( LV2,RANK:10 )
|
-
-
3 楼
LYQINGYE
ImageBase -> NewImageBase 需要重定位的地址 - OldImageBase + NewImageBase
不是,我这是直接对二进制程序进行修改,不是用工具,所以不能直接修改整个地址,而是只能修改表里的VA和TypeOffset,问题是我这样改却运行不起来,想问下,这样改对不对,如果对的话可能是我代码写的有问题
|
能力值:
( LV9,RANK:190 )
|
-
-
4 楼
修改映像基地址就要对pe大手术了,而且成功率也不是有多大,除非你有源码编译的符号信息。要把pe有关所有va项全部修改
|
能力值:
( LV2,RANK:10 )
|
-
-
5 楼
linziqingl
修改映像基地址就要对pe大手术了,而且成功率也不是有多大,除非你有源码编译的符号信息。要把pe有关所有va项全部修改
前辈好,如果原来映像基地址是0x400000,把它改成0x500000后是不是只需要把重定位表里的所有VirtualAddress都加上0x100000就可以了
|
能力值:
( LV2,RANK:10 )
|
-
-
6 楼
请问楼主解决了吗?我也在尝试自己修改ImageBase,然后写程序自己修复,也是遇到了楼主一样的问题
|
能力值:
( LV4,RANK:50 )
|
-
-
7 楼
#include <windows.h>
#include <tchar.h>
#define PAGE_SIZE 0x1000
#pragma pack(push, 1)
// 重定位表结构
typedef struct _OffTable{
USHORT addr:12;
USHORT flags:4;
}OffTable, *pOffTable;
typedef struct _RELOADTABLE{
DWORD StartVirtualAddress;
DWORD size;
OffTable Table[1];
}RELOADTABLE, *pRELOADTABLE;
#pragma pack(pop)
// 修改重定位表 hmodule 加载的地址
// BaseAddress 将要重定位的地址,用来检查HOOK或者恢复hook时候用
BOOL RelocAddr(LPBYTE hModule, LPBYTE BaseAddress )
{
if (hModule == NULL)
{
return FALSE;
}
PIMAGE_DOS_HEADER Header = (PIMAGE_DOS_HEADER)hModule;
if( Header->e_magic != IMAGE_DOS_SIGNATURE )
{
return FALSE;
}
if ( Header->e_lfanew > 0x1000 || Header->e_lfanew < 0 )
{
return FALSE;
}
PIMAGE_NT_HEADERS peheader =
(PIMAGE_NT_HEADERS)((LPBYTE)Header + Header->e_lfanew);
if (peheader->Signature != IMAGE_NT_SIGNATURE ||
peheader->FileHeader.Machine != IMAGE_FILE_MACHINE_I386 && // x86
peheader->FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64 ) // x64
{
return FALSE;
}
DWORD dwsizeOfImage = peheader->OptionalHeader.SizeOfImage;
LPBYTE dwAddress = (LPBYTE)peheader->OptionalHeader.ImageBase;
peheader->OptionalHeader.ImageBase = (DWORD)BaseAddress;
if ( dwAddress == BaseAddress )
{
// 基地址不变
return TRUE;
}
// PE 头 offset 0x98
DWORD pReloadOffset = peheader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
if ( pReloadOffset > dwsizeOfImage )
{
// 不落在这个文件内,重定位表错误
return false;
}
PIMAGE_SECTION_HEADER SectionHeader = (PIMAGE_SECTION_HEADER)( (DWORD)peheader +
sizeof(peheader->FileHeader) +
sizeof(peheader->Signature) +
peheader->FileHeader.SizeOfOptionalHeader ); // 节表项的开始
WORD SectionNum = peheader->FileHeader.NumberOfSections; // 节数目
pRELOADTABLE reloadaddr = NULL;
for (WORD i=0; i<SectionNum; i++) // 将节一个个复制到内存中
{
if (pReloadOffset>=SectionHeader[i].VirtualAddress && pReloadOffset<=SectionHeader[i].VirtualAddress+SectionHeader[i].SizeOfRawData)
{
reloadaddr = (pRELOADTABLE)(pReloadOffset-SectionHeader[i].VirtualAddress+SectionHeader[i].PointerToRawData+hModule);
break;
}
}
// 遍历重定位表
while ( reloadaddr->StartVirtualAddress != NULL && reloadaddr->size != NULL )
{
for (DWORD i=0; i<(reloadaddr->size-8)/2 ; i++)
{
__try
{
if ( reloadaddr->Table[i].flags == 3 )
{
PDWORD* OffsetAddress;
DWORD dwOffset = (DWORD)(reloadaddr->Table[i].addr + reloadaddr->StartVirtualAddress);
for (WORD s=0; s<SectionNum; s++)
{
if (dwOffset>=SectionHeader[s].VirtualAddress && dwOffset<=SectionHeader[s].VirtualAddress+SectionHeader[s].SizeOfRawData)
{
OffsetAddress = (PDWORD*)(dwOffset-SectionHeader[s].VirtualAddress+SectionHeader[s].PointerToRawData+hModule);
break;
}
}
*OffsetAddress = (LPDWORD)((LPBYTE)(*OffsetAddress) - dwAddress + BaseAddress);
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
continue;
}
}
reloadaddr = (pRELOADTABLE) ((DWORD)reloadaddr + reloadaddr->size );
}
return TRUE;
}
BOOL ReBuildDll(PTSTR szFileName, LPBYTE BaseAddress)
{
HANDLE handle = CreateFile(szFileName,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (handle == INVALID_HANDLE_VALUE)
{
return FALSE;
}
DWORD dwBytes;
DWORD dwFileSize = GetFileSize(handle, NULL);
LPBYTE lpBuf = (LPBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwFileSize);
ReadFile(handle, lpBuf, dwFileSize, &dwBytes, NULL);
if( RelocAddr(lpBuf, BaseAddress) )
{
SetFilePointer(handle, 0, NULL, FILE_BEGIN);
WriteFile(handle, lpBuf, dwFileSize, &dwBytes, NULL);
CloseHandle(handle);
return TRUE;
}
CloseHandle(handle);
return FALSE;
}
int main(int argc, char* argv[])
{
ReBuildDll(TEXT("CRC32.DLL"), (LPBYTE)0x08000000);
return 0;
}
|
能力值:
( LV2,RANK:10 )
|
-
-
8 楼
瀚海云烟
#include& ...
看了瀚海云烟的代码之后发现自己一直理解错了,之前一直纠结在如何把很大的差值放到每两个字节的低12位,还是放在每一块的VirtualAddress,两个都试过了,一改DLL就不能使用了,看完他的代码之后才明白,三项加起来之后才是要修改的地址,而我之前一直想修改这三项中的VirtualAddress和低12位,瀚海云烟的是将DLL加载,我的是直接把文件中的原封不动的读到内存,然后再改ImageBase,最后保存到文件,这其中还要有一步RvaToFoa的过程,因为我不是加载,另外,看了他的代码发现我以前只是知道结构体的位字段,但是并没有使用过,今日一见,确实思路很清晰,我是靠指针之间的强转跳过8字节,用与运算得到12位,每一次都要写的很长,还容易出错,从中学习了很多
|
能力值:
( LV9,RANK:190 )
|
-
-
9 楼
Greebees
前辈好,如果原来映像基地址是0x400000,把它改成0x500000后是不是只需要把重定位表里的所有VirtualAddress都加上0x100000就可以了
我记得以前好像在看雪上上传过一个源码是隐藏重定位信息的,对你应该有一下参考价值吧,你自己找找,我都不记得了。
|
能力值:
( LV4,RANK:50 )
|
-
-
10 楼
|
能力值:
( LV2,RANK:10 )
|
-
-
11 楼
//把修复重定位表这部分相关的都贴出来了,自己写的
//希望有帮助,昨天我也不清楚到底是怎么修复的
// FileBuffer
BYTE* p = NULL;
void openFile()
{
FILE *fp = fopen("C:\\Users\\Administrator\\Desktop\\Dynamic Link Library.dll", "rb");
fseek(fp, 0, SEEK_END);
fileLen = ftell(fp);
p = (BYTE*)malloc(fileLen);
memset(p, 0, fileLen);
fseek(fp, 0, SEEK_SET);
fread(p, fileLen, 1, fp);
fclose(fp);
return ;
}
//在文件中还是拉伸后在内存中都可以按这个函数找
void* Switch(int index, BYTE* base)
{
BYTE* pBuf = base;
//1 DOS
IMAGE_DOS_HEADER* pDos = (IMAGE_DOS_HEADER *)pBuf;
//2 NT
IMAGE_NT_HEADERS32* pNt = (IMAGE_NT_HEADERS32 *)(pBuf + pDos->e_lfanew);
//3 PE
IMAGE_FILE_HEADER* pFile = (IMAGE_FILE_HEADER *)&pNt->FileHeader;
//4 Option
IMAGE_OPTIONAL_HEADER32* pOption = (IMAGE_OPTIONAL_HEADER32 *)&pNt->OptionalHeader;
//5 DataDirectoy
IMAGE_DATA_DIRECTORY* pDataDir = pOption->DataDirectory;
//6 Section table
IMAGE_SECTION_HEADER* pSection = (IMAGE_SECTION_HEADER *)( (long)pNt + (long)&(((IMAGE_NT_HEADERS32 *)0)->OptionalHeader) + pFile->SizeOfOptionalHeader );
switch(index)
{
case 1:
return pDos;
case 2:
return pNt;
case 3:
return pFile;
case 4:
return pOption;
case 5:
return pDataDir;
case 6:
return pSection;
}
return NULL;
}
DWORD RvaToFoa(DWORD rva)
{
int i;
//1 DOS
IMAGE_DOS_HEADER* pDos = (IMAGE_DOS_HEADER *)Switch(1, p);
//2 NT
IMAGE_NT_HEADERS32* pNt = (IMAGE_NT_HEADERS32 *)Switch(2, p);
//3 PE
IMAGE_FILE_HEADER* pFile = (IMAGE_FILE_HEADER *)Switch(3, p);
//4 Option
IMAGE_OPTIONAL_HEADER32* pOption = (IMAGE_OPTIONAL_HEADER32 *)Switch(4, p);
//5 DataDirectoy
IMAGE_DATA_DIRECTORY* pDataDir = (IMAGE_DATA_DIRECTORY*)Switch(5, p);
//6 Section table
IMAGE_SECTION_HEADER* pSection = (IMAGE_SECTION_HEADER *)Switch(6, p);
// 如果rva在第一个节之前
if(rva <= pSection->VirtualAddress)
{
return rva;
}
for(i=0 ; i < pFile->NumberOfSections ; i++)
{
if(
(rva >= pSection->VirtualAddress) &&
(rva < pSection->VirtualAddress + pSection->Misc.VirtualSize)
)
{
return rva - pSection->VirtualAddress + pSection->PointerToRawData;
}
pSection++;
}
return -1;
}
//数据目录表项
void* AddressOfTable(int index)
{
IMAGE_DOS_HEADER* pDos = (IMAGE_DOS_HEADER*)Switch(1, p);
IMAGE_FILE_HEADER* pFile = (IMAGE_FILE_HEADER*)Switch(3, p);
IMAGE_OPTIONAL_HEADER32* pOption = (IMAGE_OPTIONAL_HEADER32*)Switch(4, p);
IMAGE_DATA_DIRECTORY* pDataDir = (IMAGE_DATA_DIRECTORY *)Switch(5, p);
//判断表存在
if(pDataDir[index].VirtualAddress == 0)
{
printf("空表\n");
return NULL;
}
switch(index)
{
case 0:
return (BYTE *)pDos + RvaToFoa(pDataDir[0].VirtualAddress);
case 1:
return (BYTE *)pDos + RvaToFoa(pDataDir[1].VirtualAddress);
case 5:
return (BYTE *)pDos + RvaToFoa(pDataDir[5].VirtualAddress);
}
return NULL;
}
// 修复 重定位表
void restoreRelocation()
{
//重定位表
IMAGE_BASE_RELOCATION *pstart;
WORD *value; //要修改的项
DWORD count; //需要重定位的个数
DWORD size;
DWORD tmp; //保存低12位
DWORD imageBase; //旧的ImageBase
DWORD i;
DWORD *offest;
IMAGE_DOS_HEADER* pDos = (IMAGE_DOS_HEADER*)Switch(1, p);
IMAGE_FILE_HEADER* pFile = (IMAGE_FILE_HEADER*)Switch(3, p);
IMAGE_OPTIONAL_HEADER32* pOption = (IMAGE_OPTIONAL_HEADER32*)Switch(4, p);
IMAGE_DATA_DIRECTORY* pDataDir = (IMAGE_DATA_DIRECTORY *)Switch(5, p);
IMAGE_SECTION_HEADER* pSection = (IMAGE_SECTION_HEADER *)Switch(6, p);
//重定位表
pstart = (IMAGE_BASE_RELOCATION *)AddressOfTable(5);
// oldImageBase
imageBase = pOption->ImageBase;
// newImageBase
pOption->ImageBase = 0x500000;
while(pstart->VirtualAddress != 0 && pstart->SizeOfBlock != 0)
{
//printf("pstart->VirtualAddress: %X\n", pstart->VirtualAddress);
count = (pstart->SizeOfBlock - 8) / 2;
size = pstart->SizeOfBlock;
// 跳过8字节
value = (WORD *)( (BYTE *)pstart + 8 );
for(i=0 ; i < count ; i++)
{
// 取高4位
tmp = *value & 0x0000F000;
// 高四位是3
if(tmp == 0x3000)
{
//输出低12位
//printf("%X\n", (*value & 0x00000FFF) + pstart->VirtualAddress);
//文件原封不动读到内存中pDos就是"MZ",每一块的VirtualAddress + 低12位的和是rva
//我相当于在文件中找,所以要转成foa
offest = (DWORD *)( (BYTE *)pDos + RvaToFoa( pstart->VirtualAddress + (*value & 0x00000FFF) ) );
//每一项都改
*offest = *offest - imageBase + pOption->ImageBase;
}
value++; //2
}
pstart = (IMAGE_BASE_RELOCATION *)( (BYTE *)pstart + size );
}
return ;
}
int main()
{
openFile();
//testAddSection();
//FileBufferToImageBuffer();
//testAddCode();
//testEnlargeSection();
//testMergeSection();
//ImageBufferToFileBuffer();
//printDataDirectory();
//myPlus = (lpPlus)GetFounctionAddrByIndex(p, 12);
//printf("%08X\n", myPlus);
//myPlus = (lpPlus)GetFounctionAddrByName(p, "Plus");
//printf("%08X\n", myPlus);
//printRelocation();
//moveExportTable();
//moveRelocation();
//修复重定位表
restoreRelocation();
//printImportTable();
closeFile();
free(p);
//free(p2);
//free(p3);
return 0;
}
|
能力值:
( LV2,RANK:10 )
|
-
-
12 楼
一花季落
//把修复重定位表这部分相关的都贴出来了,自己写的
//希望有帮助,昨天我也不清楚到底是怎么修复的
// FileBuffer
BYTE*&n ...
太谢谢啦前辈!!!!原来是我之前对重定位理解错误了,看完代码真是醍醐灌顶
|
能力值:
( LV2,RANK:10 )
|
-
-
13 楼
一花季落
//把修复重定位表这部分相关的都贴出来了,自己写的
//希望有帮助,昨天我也不清楚到底是怎么修复的
// FileBuffer
BYTE*&n ...
不过还有个疑问,在修复重定位表函数的循坏那块,既然判断高4位是否为3是这样写的: tmp = *value & 0x0000F000;,那为什么输出低12位就是这样:printf("%X\n", (*value & 0x00000FFF) + pstart->VirtualAddress);,而不是/printf("%X\n", (*value & 0x0FFF0000) + pstart->VirtualAddress);呢
|
能力值:
( LV2,RANK:10 )
|
-
-
14 楼
装载后不用进行DLL初始化吗?
|
能力值:
( LV2,RANK:10 )
|
-
-
15 楼
Greebees
不过还有个疑问,在修复重定位表函数的循坏那块,既然判断高4位是否为3是这样写的: tmp = *value & 0x0000F000;,那为什么输出低12位就是这样:printf(" ...
最近一直在写东西,然后又出去玩了两天,有一段时间没有上论坛。 下面说一下原因,因为重定位表里面的每一项数据是2个字节,所以我才说高4位和低12位,16位合起来是两个字节,因为我平常在写16进制数的时候基本上都是写32位,4个字节的,所以让你误解了,这下你 应该能明白。
|
能力值:
(RANK:10 )
|
-
-
16 楼
请问楼主解决了吗?
|
能力值:
( LV2,RANK:10 )
|
-
-
17 楼
|
能力值:
( LV2,RANK:10 )
|
-
-
18 楼
谁能看看我的代码啊 也是重定位的问题 哪里错了啊
|
|
|