首页
社区
课程
招聘
打造MyGetProcAddress函数(Delphi源码)
2004-5-6 12:01 14461

打造MyGetProcAddress函数(Delphi源码)

2004-5-6 12:01
14461
function MyGetProcAddress(hModule: HMODULE; lpProcName: LPCSTR): FARPROC; stdcall;

function MyGetProcAddress(hModule: HMODULE; lpProcName: LPCSTR): FARPROC;
var
  DataDirectory: TImageDataDirectory;
  P1: ^Cardinal;
  P2: ^Word;
  Base, NumberOfNames, AddressOfFunctions, AddressOfNames, AddressOfNameOrdinals, i, Ordinal: Cardinal;
  TempStr1, TempStr2: string;
begin
  Result := nil;
  DataDirectory := PImageNtHeaders(Cardinal(hModule) + Cardinal(PImageDosHeader(hModule)^._lfanew))^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
  P1 := Pointer(hModule + DataDirectory.VirtualAddress + 16);
  Base := P1^; //输出函数的起始序号。一般为1。
  P1 := Pointer(hModule + DataDirectory.VirtualAddress + 24);
  NumberOfNames := P1^; //输出函数名的指针的数组中的元素个数,也是输出函数名对应的序号的数组中的元素个数。
  P1 := Pointer(hModule + DataDirectory.VirtualAddress + 28);
  AddressOfFunctions := P1^; //一个RVA,指向输出函数入口地址的数组。
  P1 := Pointer(hModule + DataDirectory.VirtualAddress + 32);
  AddressOfNames := P1^; //一个RVA,指向输出函数名的指针的数组。
  P1 := Pointer(hModule + DataDirectory.VirtualAddress + 36);
  AddressOfNameOrdinals := P1^; //一个RVA,指向输出函数名对应的序号的数组。
  Ordinal := 0;
  if Cardinal(lpProcName) > $0000FFFF then
  begin
    //lpProcName参数指向函数名
    TempStr1 := PChar(lpProcName); //要找的函数名
    for i := 1 to NumberOfNames do
    begin
      //按顺序在输出函数名中找
      P1 := Pointer(hModule + AddressOfNames + (i - 1) * 4);
      TempStr2 := PChar(hModule + P1^); //当前输出函数名
      if TempStr1 = TempStr2 then
      begin
        //找到输出函数
        P2 := Pointer(hModule + AddressOfNameOrdinals + (i - 1) * 2);
        //获得序号,不必减Base
        Ordinal := P2^;
        Break;
      end;
    end;
  end
  else
    //lpProcName传过来的是序号,需减Base
    Ordinal := Cardinal(lpProcName) - Base;
  P1 := Pointer(hModule + AddressOfFunctions + Ordinal * 4); //P1^为函数入口RVA
  if (P1^ >= DataDirectory.VirtualAddress) and (P1^ <= DataDirectory.VirtualAddress + DataDirectory.Size) then
  begin
    //!!!入口RVA在输出表中,指向另一DLL的某函数,这一点很容易被忽视,很少有教程提到,也许是没仔细看!!!
    TempStr1 := PChar(hModule + P1^); //DLL.函数
    TempStr2 := TempStr1;
    while Pos('.', TempStr2) > 0 do
      TempStr2 := Copy(TempStr2, Pos('.', TempStr2) + 1, Length(TempStr2) - Pos('.', TempStr2));
    TempStr1 := Copy(TempStr1, 1, Length(TempStr1) - Length(TempStr2) - 1); //TempStr1是DLL名,TempStr2是函数名
    //递归调用获取新的函数地址
    Base := GetModuleHandle(PChar(TempStr1));
    if Base = 0 then
      Base := LoadLibrary(PChar(TempStr1));
    if Base > 0 then
      Result := MyGetProcAddress(Base, PChar(TempStr2));
  end
  else
    //RVA+基址就是函数的真实入口了
    Result := Pointer(hModule + P1^);
  //结果Result := GetProcAddress(hModule, lpProcName);
end;

相关:
  _IMAGE_DATA_DIRECTORY = record
    VirtualAddress: DWORD;
    Size: DWORD;
  end;
  {$EXTERNALSYM _IMAGE_DATA_DIRECTORY}
  TImageDataDirectory = _IMAGE_DATA_DIRECTORY;

  PImageExportDirectory = ^TImageExportDirectory;
  _IMAGE_EXPORT_DIRECTORY = packed record
      Characteristics: DWord;
      TimeDateStamp: DWord;
      MajorVersion: Word;
      MinorVersion: Word;
      Name: DWord;
      Base: DWord;
      NumberOfFunctions: DWord;
      NumberOfNames: DWord;
      AddressOfFunctions: ^PDWORD;
      AddressOfNames: ^PDWORD;
      AddressOfNameOrdinals: ^PWord;
  end;
  {$EXTERNALSYM _IMAGE_EXPORT_DIRECTORY}
  TImageExportDirectory = _IMAGE_EXPORT_DIRECTORY;

这是我用来在EncryptPE新版壳中处理IAT的源代码,98、2003下测试通过。如果你发现问题请告诉我!
假如你是Cracker,看到这段代码,你准备如何设断,避开IAT加密呢?

EncryptPE作者老王(wfs)
2004.5.6

[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

收藏
点赞10
打赏
分享
最新回复 (15)
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
狗到猫宁 2004-5-6 14:16
2
0
很多cracker看源代码反而看不懂
倒是看反汇编代码更容易理解一些
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Aming 2004-5-6 14:27
3
0
同一函数,我用在VB_Shell里面的。
Function GetProcAddressDirectly(ByVal lpImageDosHeader As IMAGE_DOS_HEADER Ptr, FuncName As Asciiz) As Dword
    Dim lpImageNtHeaders          As Local IMAGE_NT_HEADERS Ptr
    Dim lpImageExportDirectory    As Local IMAGE_EXPORT_DIRECTORY Ptr
    Dim lpNameOrdinals            As Local Word Ptr
    Dim lpFunctions               As Local Dword Ptr
    Dim lpName                    As Local Dword Ptr
    Dim lpExpFuncName             As Local Asciiz Ptr
    Dim i                         As Local Dword
    Dim j                         As Local Dword
    Dim lpFuncName                As Asciiz Ptr

    If @lpImageDosHeader.e_magic <> %IMAGE_DOS_SIGNATURE Then ' invalid DOS signature
        Function = 1
        MsgBox "Invalid DOS signature",%MB_ICONWARNING,"Error in GetProcAddressDirectly()"
        Exit Function
    End If
    lpImageNtHeaders = lpImageDosHeader + @lpImageDosHeader.e_lfanew
   '================================

    If @lpImageNtHeaders.Signature <> %IMAGE_NT_SIGNATURE Then ' Invalid NT signature
        Function = 1
        MsgBox "Invalid NT signature",%MB_ICONWARNING,"Error in GetProcAddressDirectly()"
        Exit Function
    End If
   '================================

    If @lpImageNtHeaders.FileHeader.SizeOfOptionalHeader <> SizeOf(@lpImageNtHeaders.OptionalHeader) Or _
        @lpImageNtHeaders.OptionalHeader.Magic <> %IMAGE_NT_OPTIONAL_HDR32_MAGIC Then
        Function = 0
        MsgBox "SizeOfOptionalHeader or OptionalHeader.Magic",%MB_ICONWARNING,"Error in GetProcAddressDirectly()"
        Exit Function
    End If
    lpImageExportDirectory = @lpImageNtHeaders.OptionalHeader.DataDirectory(%IMAGE_DIRECTORY_ENTRY_EXPORT).VirtualAddress
   '================================

    If lpImageExportDirectory = 0 Then
        Function = 0
        MsgBox "lpImageExportDirectory",%MB_ICONWARNING,"Error in GetProcAddressDirectly()"
        Exit Function
    End If
    lpImageExportDirectory = lpImageExportDirectory + lpImageDosHeader
   '================================

    lpNameOrdinals = @lpImageExportDirectory.AddressOfNameOrdinals + lpImageDosHeader
    lpName         = @lpImageExportDirectory.AddressOfNames        + lpImageDosHeader
    lpFunctions    = @lpImageExportDirectory.AddressOfFunctions    + lpImageDosHeader
   '================================

    lpFuncName = VarPtr(FuncName)
   '================================

    If HiWrd(lpFuncName) Then ' Name
       For i = 0 To @lpImageExportDirectory.NumberOfFunctions - 1
          If @lpFunctions[i] Then
             For j = 0 To @lpImageExportDirectory.NumberOfNames - 1
                If @lpNameOrdinals[j] = i Then
                   lpExpFuncName = @lpName[j] + lpImageDosHeader
                   If @lpExpFuncName = FuncName Then Function = @lpFunctions[i] + lpImageDosHeader : Exit Function
                End If
             Next
          End If
       Next

    Else
       For i = 0 To @lpImageExportDirectory.NumberOfFunctions - 1
          If lpFuncName = @lpImageExportDirectory.nBase + i Then
             If  @lpFunctions[i] Then Function = @lpFunctions[i] + lpImageDosHeader
             Exit Function
          End If
       Next
    End If
   '================================

End Function

VC:
DWORD GetProcAddressDirectly(PIMAGE_DOS_HEADER lpImageDosHeader, char * FuncName)
{
    PIMAGE_NT_HEADERS lpImageNtHeaders;
    PIMAGE_EXPORT_DIRECTORY pExportDir;
    PWORD lpNameOrdinals;
    unsigned char * lpFunctions;
    DWORD * lpName;
    char * lpExpFuncName;
    DWORD i;
    DWORD j;
    char * lpFuncName;

    if(lpImageDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
        {
        MessageBox(NULL,"Invalid DOS signature",0,0);
        return 1;
        }
   
    lpImageNtHeaders = (PIMAGE_NT_HEADERS)(lpImageDosHeader + lpImageDosHeader->e_lfanew);
       
    if (lpImageNtHeaders->Signature != IMAGE_NT_SIGNATURE)
        {
                MessageBox(NULL,"Invalid NT signature",0,0);
        return 1;
    }
       
    if ((lpImageNtHeaders->FileHeader.SizeOfOptionalHeader != sizeof(lpImageNtHeaders->OptionalHeader)) ||
        (lpImageNtHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC))
        {
                MessageBox(NULL,"SizeOfOptionalHeader or OptionalHeader->Magic",0,0);
        return 0;
    }

        DWORD exportsStartRVA, exportsEndRVA;
    PIMAGE_NT_HEADERS pNTHeader;
        //PIMAGE_NT_HEADERS64 pNTHeader64;
    PBYTE pImageBase = (PBYTE)lpImageDosHeader;
   
        // Make pointers to 32 and 64 bit versions of the header.
    pNTHeader = MakePtr( PIMAGE_NT_HEADERS, lpImageDosHeader,
                                lpImageDosHeader->e_lfanew );

    exportsStartRVA = GetImgDirEntryRVA(pNTHeader,IMAGE_DIRECTORY_ENTRY_EXPORT);
    exportsEndRVA = exportsStartRVA +
                                           GetImgDirEntrySize(pNTHeader, IMAGE_DIRECTORY_ENTRY_EXPORT);

    // Get the IMAGE_SECTION_HEADER that contains the exports.  This is
    // usually the .edata section, but doesn't have to be.
        PIMAGE_SECTION_HEADER header;
    header = GetEnclosingSectionHeader( exportsStartRVA, pNTHeader );
    if ( !header ) return 0;

        INT delta;
    delta = (INT)(header->VirtualAddress - header->PointerToRawData);
    pExportDir = (PIMAGE_EXPORT_DIRECTORY)GetPtrFromRVA(exportsStartRVA, pNTHeader, pImageBase);

       
    pExportDir =(PIMAGE_EXPORT_DIRECTORY) (lpImageNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
       
    if (pExportDir == 0)
        {
                MessageBox(NULL,"Error in GetProcAddressDirectly()",0,0);
        return 0;
    }
       
    pExportDir =(PIMAGE_EXPORT_DIRECTORY) (DWORD)pExportDir + (DWORD)lpImageDosHeader;
       
    lpNameOrdinals =(unsigned short *)(pExportDir->AddressOfNameOrdinals + lpImageDosHeader);
    //lpNameOrdinals =        (PWORD)        GetPtrFromRVA( pExportDir->AddressOfNameOrdinals, pNTHeader, pImageBase );
    lpName         =(DWORD *) (pExportDir->AddressOfNames        + lpImageDosHeader);
    lpFunctions    =(unsigned char *) (pExportDir->AddressOfFunctions    + lpImageDosHeader);

        //PDWORD pdwFunctions;

    lpFuncName = FuncName;
       
    if(HIWORD(lpFuncName)!=0 )
        {
                for( i = 0;i<=pExportDir->NumberOfFunctions - 1;i++)
                {
                        DWORD entryPointRVA = *lpFunctions;
                       
                        if ( entryPointRVA == 0 ) continue;  // Skip over gaps in exported function
                                                                 // ordinals (the entrypoint is 0 for
                       
                        for( j = 0;j<=pExportDir->NumberOfNames - 1;j++)
                        {
                                if( lpNameOrdinals[j] == i)
                                {
                                        lpExpFuncName = (char *) (lpName[j] + lpImageDosHeader);
                                        if(lpExpFuncName = FuncName)  return (unsigned long) (lpFunctions[i] + lpImageDosHeader);
                                }
                        }
                }
        }
    else
        {
                for (i = 0 ;i<=pExportDir->NumberOfFunctions - 1;i++)
                {
                        if (lpFuncName == (char *)(pExportDir->Base + i))
                        {
                                if (lpFunctions[i]) return (unsigned long) (lpFunctions[i] + lpImageDosHeader);
                        }
                }
    }
        return 0;
}
雪    币: 194
活跃值: (25)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
baron 2004-5-7 03:06
4
0
dephi的vcl太肥了,dephi不适合用来做加壳,加密程序
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
狗到猫宁 2004-5-7 11:47
5
0
最初由 baron 发布
dephi的vcl太肥了,dephi不适合用来做加壳,加密程序


你不知道asprotect也是delphi做的吗
雪    币: 411
活跃值: (1160)
能力值: ( LV9,RANK:810 )
在线值:
发帖
回帖
粉丝
David 20 2004-5-7 11:51
6
0
最初由 狗到猫宁 发布


你不知道asprotect也是delphi做的吗


加密壳根本不考虑文件大小,必要时候52k to 100M 都有可能.

另外 Dephi 很容易保护它自己,汇编的破解更容易.
雪    币: 674
活跃值: (1684)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
daxia200N 6 2004-5-7 14:32
7
0
Acpro,Aspro,幻影,老王加密壳,都是Delphi写的,Delphi功能很强大。
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
狗到猫宁 2004-5-7 16:09
8
0
最初由 daxia200N 发布
Acpro,Aspro,幻影,老王加密壳,都是Delphi写的,Delphi功能很强大。


如何证明幻影是Delphi写的?
雪    币: 513
活跃值: (2228)
能力值: ( LV9,RANK:2130 )
在线值:
发帖
回帖
粉丝
loveboom 53 2004-5-7 18:33
9
0
谢谢老位老大(老王and aming)
to aming:
aming的vb功力实在是利害,看到他,我就失望的说(以前我自认为我的VB也学到几斤吧,看到他,才知道自己不知道什么时候才能学到aming现在这等功力)
对了,aming可不可以共享一下你的转换成VB后的相关pe的函数,常量等相关东东?先在这里谢过了.

to 老王:
  你的方法在pelock里已经用过(指hook api的思想,pelock自己用代码替换了几个api),要对付你的hook api也不难,像hexer等牛那样,我一行一行看代码,不会看不出来的。

.
最初由 狗到猫宁 发布


如何证明幻影是Delphi写的?

幻影有什么写的都不知道,晕,还敢附加这样利害的信息,我看多数是个骗钱的来的.
狗到猫宁 签名


高价接手外挂破解业务

破外挂高手不可能对常见的加壳工具没有大概的了解.
雪    币: 513
活跃值: (2228)
能力值: ( LV9,RANK:2130 )
在线值:
发帖
回帖
粉丝
loveboom 53 2004-5-7 19:01
10
0
最初由 David 发布


加密壳根本不考虑文件大小,必要时候52k to 100M 都有可能.

另外 Dephi 很容易保护它自己,汇编的破解更容易.

呵呵,没有这样的事了,delphi只是在写的方面方便而已,保护自己我倒不觉得怎么样.
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
狗到猫宁 2004-5-7 19:16
11
0
最初由 loveboom 发布
谢谢老位老大(老王and aming)
to aming:
aming的vb功力实在是利害,看到他,我就失望的说(以前我自认为我的VB也学到几斤吧,看到他,才知道自己不知道什么时候才能学到aming现在这等功力)
对了,aming可不可以共享一下你的转换成VB后的相关pe的函数,常量等相关东东?先在这里谢过了.

to 老王:
你的方法在pelock里已经用过(指hook api的思想,pelock自己用代码替换了几个api),要对付你的hook api也不难,像hexer等牛那样,我一行一行看代码,不会看不出来的。

.
幻影有什么写的都不知道,晕,还敢附加这样利害的信息,我看多数是个骗钱的来的.

破外挂高手不可能对常见的加壳工具没有大概的了解.


几十万行代码什么牛都会吐血

会脱壳一定要懂加壳吗?壳都是垃圾,不用了解也一样可以脱,尤其是幻影
幻影界面主程序是BCB编译的俺还知道,dll是什么做的你知道吗?
BCB = DELPHI ?
雪    币: 260
活跃值: (81)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
pll621 2004-5-8 00:55
12
0
function MyGetProcAddress(hModule: HMODULE; lpProcName: LPCSTR): FARPROC; stdcall
将导致调用的时候是
push lpProcName
push hModule
call MyGetProcAddress
形式
一般我会断LoadLibrary函数(此函数我想一般人不会自己去实现它),然后
观察对kenerl32.dll等重要函数的loalibray.得到的返回值,下对这个值得
内存访问断点.很容易找到你实现的MyGetProcAddress函数,一开始可能看不出来但是看几次堆栈后ret就知道你这个玩意就是模仿getprocaddress了,
雪    币: 274
活跃值: (165)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
老王 1 2004-5-8 11:58
13
0
最初由 pll621 发布
function MyGetProcAddress(hModule: HMODULE; lpProcName: LPCSTR): FARPROC; stdcall
将导致调用的时候是
push lpProcName
push hModule
call MyGetProcAddress
形式
一般我会断LoadLibrary函数(此函数我想一般人不会自己去实现它),然后
观察对kenerl32.dll等重要函数的loalibray.得到的返回值,下对这个值得
内存访问断点.很容易找到你实现的MyGetProcAddress函数,一开始可能看不出来但是看几次堆栈后ret就知道你这个玩意就是模仿getprocaddress了,


我还在想是否应该先实现一个MyLoadLibrary呢,正好你说到这了,呵呵!
不过LoadLibrary不一定执行,GetModuleHandle不成功才执行,哎,你可能会对GetModuleHandle下断,能不能实现MyGetModuleHandle呢?
雪    币: 260
活跃值: (81)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
pll621 2004-5-8 12:48
14
0
最初由 老王 发布


我还在想是否应该先实现一个MyLoadLibrary呢,正好你说到这了,呵呵!
不过LoadLibrary不一定执行,GetModuleHandle不成功才执行,哎,你可能会对GetModuleHandle下断,能不能实现MyGetModuleHandle呢?

理论上能实现,但是实际上我也不知道...GetModuleHandle里面的底层的玩意你知道多少....而且还要兼容不同的系统...这可不像getproc   那么简单了..估计应该有投机取巧的办法..不过我没有仔细的研究过..只能请教研究过的人了..
雪    币: 371
活跃值: (790)
能力值: ( LV12,RANK:570 )
在线值:
发帖
回帖
粉丝
kongfoo 14 2004-5-8 14:11
15
0
GetModuleHandle返回的是ImageBase,能投机取巧吧:)
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Aming 2004-5-8 16:44
16
0
最初由 老王 发布


我还在想是否应该先实现一个MyLoadLibrary呢,正好你说到这了,呵呵!
不过LoadLibrary不一定执行,GetModuleHandle不成功才执行,哎,你可能会对GetModuleHandle下断,能不能实现MyGetModuleHandle呢?


两个函数我都实现了,VB/VC的代码都写了。但GetModuleHandle在9X下还有点问题,导致有资源的DLL或EXE不能正常,NT/2K/XP/2K3没问题。
我考虑采用内存SwapResource。
4月初都在搞这东西,现在又丢一旁了。
游客
登录 | 注册 方可回帖
返回