首页
社区
课程
招聘
[求助]获得了一个怪异的Dos MZ Head地址
2006-7-19 16:23 5431

[求助]获得了一个怪异的Dos MZ Head地址

2006-7-19 16:23
5431
代码如下:
HANDLE hFile;
HANDLE hMapFile;
LPVOID pMapping;
OPENFILENAME ofn;
TCHAR szError[MAX_PATH};
       
ZeroMemory(&ofn, sizeof(OPENFILENAME));
ZeroMemory(szError,MAX_PATH);
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner=hwnd;
ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_EXPLORER;
ofn.nMaxFile = sizeof(szError);
ofn.lpstrFile = szError;
ofn.lpstrFilter = "ALL\0*.exe\0*.dll\0*.sys\0";

GetOpenFileName(&ofn);

hFile = CreateFile(ofn.lpstrFile,GENERIC_READ,FILE_SHARE_READ,
                   NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
hMapFile = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);
pMapping = MapViewOfFile(hMapFile,FILE_MAP_READ,0,0,0);

dosHeader = (PIMAGE_DOS_HEADER)pMapping;//转换成Dos MZ 头

问题在于: pMapping 得到的应该是00000000这样的值,但我得到的是
    f00000. 直接导致dosHeader为f00000.
    继续用这个错误的地址,却能得到正确的信息.比如能得到
    魔术数 :dosHeader->e_magic 其值与Stud_PE的值一样.
    其他的头的地址也随dosHeader的怪异而怪异:
    NtHeader = (PIMAGE_NT_HEADERS)((UINT32)dosHeader+
                                   dosHeader->e_lfanew);
    NtHeader的值也成了f000d0.通过NtHeader访问的结构和项
    的值都和Stud_PE相同.怎么会这样?

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
点赞7
打赏
分享
最新回复 (6)
雪    币: 221
活跃值: (11)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
Casimodo 1 2006-7-20 09:58
2
0
莫非, 这些地址只与低位有关?

似乎是这样了.明白了.
雪    币: 221
活跃值: (11)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
Casimodo 1 2006-7-25 10:34
3
0
如果用这个奇怪的SecionHeadedr, 在获得SectionHeader[i].Name的时候

能正确运行, 反而是我象下面处理了的不能访问:

       UINT32 Mask = 0xffff;
       SectionHeader =(PIMAGE_SECTION_HEADER)((UINT32)
                             (SectionHeader) & Mask);

更郁闷的问题是, 继续用这个奇怪的SectionHeader搞ImportTable时出错了:

      int Offset = (int) (SectionHeader->VirtualAddress -
                          SectionHeader->PointerToRawData);

      pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)(NtHeader->
                      OptionalHeader.DataDirectory
                     [IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress-
                      Offset + NtHeader->OptionalHeader.ImageBase);
   
      ThunkData = (PIMAGE_THUNK_DATA)(pImportDesc->
                   OriginalFirstThunk - Offset +
                   NtHeader->OptionalHeader.ImageBase);

      ImportBN = (PIMAGE_IMPORT_BY_NAME)(ThunkData - Offset +
                 NtHeader->OptionalHeader.ImageBase);
   
      wsprintf(szError,"%s",ImportBN->Name);
      MessageBox(hwnd,szError,"ERROR",MB_OK);

这段程序在wsprintf(szError,"%s",ImportBN->Name); 时出错

跟踪时发现, 那个Offset = 0 .

这是为什么?
雪    币: 2367
活跃值: (756)
能力值: (RANK:410 )
在线值:
发帖
回帖
粉丝
小虾 10 2006-7-25 10:55
4
0
最初由 Casimodo 发布
代码如下:
HANDLE hFile;
HANDLE hMapFile;
LPVOID pMapping;
OPENFILENAME ofn;
........

不明白,如果你用CreateFileMapping和MapViewOfFile成功的话,pMapping的指针怎么会是0呢?只有创建失败才会是0。你得出的0f00000h地址,正是MapViewOfFile成功后返回的映像地址。
雪    币: 221
活跃值: (11)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
Casimodo 1 2006-7-25 11:35
5
0
完了, 是我把pMapping的含义理解错了.

那么哪个Offset为什么会是0?

我的RVA转化错了么?
雪    币: 750
活跃值: (228)
能力值: ( LV9,RANK:780 )
在线值:
发帖
回帖
粉丝
非安全 17 2006-7-25 15:35
6
0
假设我们要列出某个PE文件的所有引入函数,可以照着下面步骤走:

1.校验文件是否是有效的PE。
2.从 DOS header 定位到 PE header。
3.获取位于 OptionalHeader 数据目录地址。
4.转至数据目录的第二个成员提取其VirtualAddress值。
5.利用上值定位第一个 IMAGE_IMPORT_DESCRIPTOR 结构。
6.检查 OriginalFirstThunk值。若不为0,顺着 OriginalFirstThunk 里的RVA值转入那个RVA数组。若 OriginalFirstThunk 为0,就改用  FirstThunk值。有些连接器生成PE文件时会置OriginalFirstThunk值为0,这应该算是个bug。不过为了安全起见,我们还是检查     OriginalFirstThunk值先。
7.对于每个数组元素,我们比对元素值是否等于IMAGE_ORDINAL_FLAG32。如果该元素值的最高二进位为1, 那么函数是由序数引入的,可以从该值的低字节提取序数。
8.如果元素值的最高二进位为0,就可将该值作为RVA转入 IMAGE_IMPORT_BY_NAME 数组,跳过 Hint 就是函数名字了。
再跳至下一个数组元素提取函数名一直到数组底部(它以null结尾)。现在我们已遍历完一个DLL的引入函数,接下去处理下一个DLL。
即跳转到下一个 IMAGE_IMPORT_DESCRIPTOR 并处理之,如此这般循环直到数组见底。(IMAGE_IMPORT_DESCRIPTOR 数组以一个全0域元素结尾)
雪    币: 139
活跃值: (111)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
bookworm 3 2006-7-26 01:53
7
0
关键在于你再写程序的时候牢记PE Header里的地址都是RVA,相对ImageBase的,不是你的process里的VA---实际地址。

    IMAGE_NT_HEADERS32 PEHeader = pMapping + dosHeader->e_lfanew;

    // your code to check the validity of PE header ...
    // do not handle x64 PE files at this moment
    if(  IMAGE_NT_SIGNATURE != PEHeader->Signature ||
         IMAGE_FILE_MACHINE_I386 != (PEHeader->FileHeader).Machine ||
         IMAGE_NT_OPTIONAL_HDR32_MAGIC != (PEHeader->OptionalHeader).Magic ||
         200 >= (PEHeader->FileHeader).NumberOfSections )
    {
         // do something as it's corrupted PE,... return E_INVALIDARG;
    }

    PIMAGE_SECTION_HEADER pSectionHeader = PEHeader + sizeof(IMAGE_NT_HEADERS32);

    // your code to browse IAT/EAT ...
游客
登录 | 注册 方可回帖
返回