元始天尊 发表于 2015-2-22 17:36:44

4gb_patch原理

花1分钟搞了一下,该程序是允许程序支持4GB空间的小工具,今天恰好又见以前人讨论这个,现在分析一下:
话休絮烦,ida载入后直接找到代表WinMain的函数sub_4015A6,
int __stdcall sub_4015A6(HINSTANCE hInstance, int a2, int a3, int a4)
{
const WCHAR *v4; // eax@1
const WCHAR *v5; // eax@1

::hInstance = hInstance;
v4 = GetCommandLineW();
v5 = sub_401218(v4);
if ( v5 )
{
    sub_401087(v5);
}
else if ( sub_4011A1() == 1 )
{
    DialogBoxParamW(hInstance, (LPCWSTR)0x65, 0, DialogFunc, 0);
}
return 0;
}
sub_401218显然是处理命令行的,不用管,进入sub_4011A1和sub_401087看看:

int __cdecl sub_401087(LPCWSTR lpExistingFileName)
{
HANDLE v1; // eax@1
void *v2; // ebx@1
int result; // eax@2
LPVOID v4; // edi@5
WCHAR NewFileName; // @1
DWORD NumberOfBytesRead; // @5
SIZE_T dwSize; // @3

sub_40162A(&NewFileName, lpExistingFileName);
sub_401638(&NewFileName, L".Backup");
CopyFileW(lpExistingFileName, &NewFileName, 1);
v1 = CreateFileW(lpExistingFileName, 0xC0000000, 1u, 0, 3u, 0x80u, 0);
v2 = v1;
if ( v1 == (HANDLE)-1 )
{
    MessageBoxW(0, L"Couldn't open executable!", L"4GB Patch", 0x30u);
    result = 0;
}
else
{
    dwSize = GetFileSize(v1, 0);
    if ( dwSize > 0x8000 )
      dwSize = 0x8000;
    v4 = VirtualAlloc(0, dwSize, 0x1000u, 4u);
    if ( ReadFile(v2, v4, dwSize, &NumberOfBytesRead, 0) )
    {
      SetFilePointer(v2, 0, 0, 0);
      *(_WORD *)((char *)v4 + *((_DWORD *)v4 + 15) + 22) |= 32u;
      WriteFile(v2, v4, dwSize, &NumberOfBytesRead, 0);
      CloseHandle(v2);
      result = 1;
    }
    else
    {
      VirtualFree(v4, 0, 0x8000u);
      CloseHandle(v2);
      MessageBoxW(0, L"Couldn't read executable!", L"4GB Patch", 0x30u);
      result = 0;
    }
}
return result;
}
int __usercall sub_4011A1@<eax>(int a1@<ebx>)
{
int result; // eax@2
WCHAR ExistingFileName; // @1
int v3; // @1
int v4; // @1
int v5; // @1
WCHAR *v6; // @1
int v7; // @1
int v8; // @1

sub_4015ED(a1, &ExistingFileName, 0, 0x208u);
sub_4015ED(a1, &v3, 0, 0x4Cu);
v4 = 0;
v6 = &ExistingFileName;
v3 = 76;
v5 = (int)L"All Files (*.*)";
v7 = 260;
v8 = (int)L"Select Executable...";
if ( GetOpenFileNameW((LPOPENFILENAMEW)&v3) )
    result = sub_401087(&ExistingFileName);
else
    result = 2;
return result;
}

可见小工具提供了命令行和选择2种方式,最后都要执行sub_401087
该函数读取文件并改写pe结构,具体为IMAGE_FILE_HEADER.Characteristics 增加IMAGE_FILE_LARGE_ADDRESSS_AWARE 意为支持2GB以上地址。。
分析完毕

0xAA55 发表于 2015-2-22 19:18:31

那路或多!原来如此简单哈。

CCInt3 发表于 2015-2-23 09:42:38

原来如此,多谢分享

0x01810 发表于 2015-2-23 11:09:52

学习了 感谢分享
页: [1]
查看完整版本: 4gb_patch原理