您的位置:首页 > 大数据 > 人工智能

PE文件格式分析系列(文章3)----一个PE文件rdata段的分析(Win32工程Release版)(二)

2012-06-23 22:25 621 查看
PE文件格式分析系列(文章3)

一个PE文件rdata段的分析(Win32工程Release版)(二)

下面分析这个PE文件rdata段的常量数据(000050A4---0000543D)
000050A0 |                         00 00 00 00 |     .... |

000050A8 | FF FF FF FF 27 11 40 00 |     '.@. | 这像一个地址00401127
000050B0 | 3B 11 40 00 5F 5F 47 4C | ;.@.__GL |
0040113B 也是

000050B8 | 4F 42 41 4C 5F 48 45 41 | OBAL_HEA | 一段字符
......

000050E0 | 00 00 00 00 72 75 6E 74 | ....runt | 运行时错误?
000050E8 | 69 6D 65 20 65 72 72 6F | ime erro |

000050F0 | 72 20 00 00 0D 0A 00 00 | r ...... |

......

00005128 | 52 36 30 32 38 0D 0A 2D | R6028..- | 好像是错误码
00005130 | 20 75 6E 61 62 6C 65 20 |  unable  | 不能初始化heap?

00005138 | 74 6F 20 69 6E 69 74 69 | to initi |

00005140 | 61 6C 69 7A 65 20 68 65 | alize he |

00005148 | 61 70 0D 0A 00 00 00 00 | ap...... |

00005150 | 52 36 30 32 37 0D 0A 2D | R6027..- |

00005158 | 20 6E 6F 74 20 65 6E 6F |  not eno |

00005160 | 75 67 68 20 73 70 61 63 | ugh spac |

00005168 | 65 20 66 6F 72 20 6C 6F | e for lo |

00005170 | 77 69 6F 20 69 6E 69 74 | wio init |

00005178 | 69 61 6C 69 7A 61 74 69 | ializati |

00005180 | 6F 6E 0D 0A 00 00 00 00 | on...... |

00005188 | 52 36 30 32 36 0D 0A 2D | R6026..- |

00005190 | 20 6E 6F 74 20 65 6E 6F |  not eno |

00005198 | 75 67 68 20 73 70 61 63 | ugh spac |

000051A0 | 65 20 66 6F 72 20 73 74 | e for st |

000051A8 | 64 69 6F 20 69 6E 69 74 | dio init |

000051B0 | 69 61 6C 69 7A 61 74 69 | ializati |

000051B8 | 6F 6E 0D 0A 00 00 00 00 | on...... |

000051C0 | 52 36 30 32 35 0D 0A 2D | R6025..- |

000051C8 | 20 70 75 72 65 20 76 69 |  pure vi |

000051D0 | 72 74 75 61 6C 20 66 75 | rtual fu |

000051D8 | 6E 63 74 69 6F 6E 20 63 | nction c |

000051E0 | 61 6C 6C 0D 0A 00 00 00 | all..... |

000051E8 | 52 36 30 32 34 0D 0A 2D | R6024..- |

...

00005370 | 4D 69 63 72 6F 73 6F 66 | Microsof | 哈哈, 这个很熟悉哦
00005378 | 74 20 56 69 73 75 61 6C | t Visual |

00005380 | 20 43 2B 2B 20 52 75 6E |  C++ Run |

00005388 | 74 69 6D 65 20 4C 69 62 | time Lib |

00005390 | 72 61 72 79 00 00 00 00 | rary.... |

...

000053E0 | 65 50 6F 70 75 70 00 00 | ePopup.. |

000053E8 | 47 65 74 41 63 74 69 76 | GetActiv |

000053F0 | 65 57 69 6E 64 6F 77 00 | eWindow. |

000053F8 | 4D 65 73 73 61 67 65 42 | MessageB |

00005400 | 6F 78 41 00 75 73 65 72 | oxA.user | 怎么也有user32.dll?

00005408 | 33 32 2E 64 6C 6C 00 00 | 32.dll.. |

...

00005428 | 22 3F 40 00 26 3F 40 00 |

00005430 | FF FF FF FF A6 40 40 00 |

00005438 | AA 40 40 00             |

分析过程如下:

OD反汇编了一下代码段, 看到一些指令
00401055  |.  68 A8504000   PUSH OFFSET 004050A8  ; FF FF FF FF

00401B0B  |.  68 B4504000   PUSH OFFSET 004050B4  ; |Arg1 = ASCII "__GLOBAL_HEAP_SELECTED"

00401ACC  |.  68 CC504000   PUSH OFFSET 004050CC  ; |Name = "__MSVCRT_HEAP_SELECT"

00401F46  |.  68 70534000   PUSH OFFSET 00405370  ; ASCII "Microsoft Visual C++ Runtime Library"

00401F1E  |.  68 98534000   PUSH OFFSET 00405398     ; ASCII ""

00401F00  |.  68 9C534000   PUSH OFFSET 0040539C     ; ASCII "Runtime Error! Program: "

00401EEC  |.  68 B8534000   PUSH OFFSET 004053B8     ; ASCII "..."

00401EAA  |.  68 BC534000   PUSH OFFSET 004053BC     ; ASCII "<program name unknown>"

00403C11  |.  68 D4534000   PUSH OFFSET 004053D4      ; /Procname = "GetLastActivePopup"

00403C09  |.  68 E8534000   PUSH OFFSET 004053E8     ; /Procname = "GetActiveWindow"

00403BF8  |.  68 F8534000   PUSH OFFSET 004053F8      ; /Procname = "MessageBoxA"

00403BE1  |.  68 04544000   PUSH OFFSET 00405404     ; /FileName = "user32.dll"

00403DB5  |.  68 10544000   PUSH OFFSET 00405410     ; |Src

00403D94  |.  68 14544000   PUSH OFFSET 00405414      ; |Src = ""

00403D63  |.  68 18544000   PUSH OFFSET 00405418

00403FB2  |.  68 30544000   PUSH OFFSET 00405430

看到了吗? 看看PUSH后面的地址, 就是对应了rdata段的位置的地址, 对应了响应的字符.
但是找不到 R6028, R6027, R6026, ...在哪里有使用.

00005128 | 52 36 30 32 38 0D 0A 2D | R6028..- | 好像是错误码

00005130 | 20 75 6E 61 62 6C 65 20 |  unable  | 不能初始化heap?

00005138 | 74 6F 20 69 6E 69 74 69 | to initi |

00005140 | 61 6C 69 7A 65 20 68 65 | alize he |

00005148 | 61 70 0D 0A 00 00 00 00 | ap...... |

其实这个Win32工程就只是一个只有WinMain函数的工程, 为什么会有这么多其他的东西的呢?

很明显, 这些字符常量是VC帮我们加的, WinMain函数并不是PE的入口点.

在VC的安装目录C:\Program Files\Microsoft Visual Studio\VC98\CRT\SRC

搜索"<program name unknown>", 找到了对应的代码在文件CRT0MSG.C中:
void __cdecl _NMSG_WRITE (int rterrnum)

{

        int tblindx;

        DWORD bytes_written;            /* bytes written */

        for ( tblindx = 0 ; tblindx < _RTERRCNT ; tblindx++ )

            if ( rterrnum == rterrs[tblindx].rterrno )

                break;

        if ( rterrnum == rterrs[tblindx].rterrno )

        {

            if ( (__error_mode == _OUT_TO_STDERR) || ((__error_mode ==

                   _OUT_TO_DEFAULT) && (__app_type == _CONSOLE_APP)) )

            {

                WriteFile( GetStdHandle(STD_ERROR_HANDLE),

                           rterrs[tblindx].rterrtxt,

                           strlen(rterrs[tblindx].rterrtxt),

                           &bytes_written,

                           NULL );

            }

            else if (rterrnum != _RT_CRNL)

            {

                #define MAXLINELEN 60

                char * pch;

                char progname[MAX_PATH];

                char outmsg[MAXLINELEN+100];

    

    // 看这里

                if (!GetModuleFileName(NULL, progname, MAX_PATH))

                    strcpy(progname, "<program name unknown>");

                pch = (char *)progname;

                if (strlen(pch) + 1 > MAXLINELEN)

                {

                    pch += strlen(progname) + 1 - MAXLINELEN;

                    strncpy(pch, "...", 3);

                }

    // 看这里

                strcpy(outmsg, "Runtime Error!\n\nProgram: ");

                strcat(outmsg, pch);

    // 看这里

                strcat(outmsg, "\n\n");

                strcat(outmsg, rterrs[tblindx].rterrtxt);

    // 看这里

                __crtMessageBoxA(outmsg,

                        "Microsoft Visual C++ Runtime Library",

                        MB_OK|MB_ICONHAND|MB_SETFOREGROUND|MB_TASKMODAL);

            }

   ....

        }

 ...

}

但还是找不到 R6028, R6027, R6026, ...在哪里有使用.

看看rterrs, rterrs是一个全局变量数组 看该数据的结构

(CRT0MSG.C中)
/* struct used to lookup and access runtime error messages */

struct rterrmsgs

{

        int rterrno;        /* error number */

        char *rterrtxt;     /* text of error message */

};

/* runtime error messages */

// 18个

static struct rterrmsgs rterrs[] =

{       

/* 2 */ { _RT_FLOAT, _RT_FLOAT_TXT }, 

/* 8 */ { _RT_SPACEARG, _RT_SPACEARG_TXT },

/* 9 */ { _RT_SPACEENV, _RT_SPACEENV_TXT },

/* 10*/ { _RT_ABORT, _RT_ABORT_TXT },

/* 16*/ { _RT_THREAD, _RT_THREAD_TXT },

/* 17*/ { _RT_LOCK, _RT_LOCK_TXT },

/* 18*/ { _RT_HEAP, _RT_HEAP_TXT },       

/* 19*/ { _RT_OPENCON, _RT_OPENCON_TXT },

/* 24*/ { _RT_ONEXIT, _RT_ONEXIT_TXT },

/* 25*/ { _RT_PUREVIRT, _RT_PUREVIRT_TXT },

/* 26*/ { _RT_STDIOINIT, _RT_STDIOINIT_TXT },

/* 27*/ { _RT_LOWIOINIT, _RT_LOWIOINIT_TXT },

/* 28*/ { _RT_HEAPINIT, _RT_HEAPINIT_TXT },

/*120*/ { _RT_DOMAIN, _RT_DOMAIN_TXT },

/*121*/ { _RT_SING, _RT_SING_TXT },

/*122*/ { _RT_TLOSS, _RT_TLOSS_TXT },

/*252*/ { _RT_CRNL, _RT_CRNL_TXT },

/*255*/ { _RT_BANNER, _RT_BANNER_TXT }

};

(CMSGS.H中)

#define EOL "\r\n"

#define _RT_FLOAT_TXT      "R6002" EOL "- floating point not loaded" EOL

#define _RT_SPACEARG_TXT   "R6008" EOL "- not enough space for arguments" EOL

#define _RT_SPACEENV_TXT   "R6009" EOL "- not enough space for environment" EOL

#define _RT_ABORT_TXT      "" EOL "abnormal program termination" EOL

#define _RT_THREAD_TXT     "R6016" EOL "- not enough space for thread data" EOL

#define _RT_LOCK_TXT       "R6017" EOL "- unexpected multithread lock error" EOL

#define _RT_HEAP_TXT       "R6018" EOL "- unexpected heap error" EOL

#define _RT_OPENCON_TXT    "R6019" EOL "- unable to open console device" EOL

#define _RT_ONEXIT_TXT     "R6024" EOL "- not enough space for _onexit/atexit table" EOL

#define _RT_PUREVIRT_TXT   "R6025" EOL "- pure virtual function call" EOL

#define _RT_STDIOINIT_TXT  "R6026" EOL "- not enough space for stdio initialization" EOL

#define _RT_LOWIOINIT_TXT  "R6027" EOL "- not enough space for lowio initialization" EOL

#define _RT_HEAPINIT_TXT   "R6028" EOL "- unable to initialize heap" EOL

#define _RT_DOMAIN_TXT     "DOMAIN error" EOL

#define _RT_SING_TXT       "SING error" EOL

#define _RT_TLOSS_TXT      "TLOSS error" EOL

#define _RT_CRNL_TXT       EOL

#define _RT_BANNER_TXT     "runtime error "

所以rdata中00005128---0000536F, 就是存储这些数据的了

但是没有在代码段中找到这些常量的地址. 为什么?
struct rterrmsgs

{

        int rterrno;        /* error number */

        char *rterrtxt;     /* text of error message */

};


因为

static struct rterrmsgs rterrs[] = {...};

代码段中直接用到的是rterrs, 而这些常量通过变量rterrs被间接使用.

rterrs是一个全局变量, 它不存储在rdata段中, 它存储在data中.


所以, 先找到rterrs的地址, 就可以找到这些字符常量的调用地址,

在data段中找rterrs的内容, 地址是什么?


找到_NMSG_WRITE函数的反汇编代码, 如下:

(有点长!!!!!)

        for ( tblindx = 0 ; tblindx < _RTERRCNT ; tblindx++ )

            if ( rterrnum == rterrs[tblindx].rterrno )

                break;

00401E2D  /$  55                     PUSH EBP                                 ; AAAAAA.00401E2D(guessed Arg1)

00401E2E  |.  8BEC                MOV EBP,ESP

00401E30  |.  81EC A4010000 SUB ESP,1A4                              ;
0x1A4长度的局部变量
00401E36  |.  8B55 08            MOV EDX,DWORD PTR SS:[EBP + 08]          ;
参数rterrnum 赋值到EDX中
00401E39  |.  33C9                  XOR ECX,ECX                                        ;
tblindx = 0
00401E3B  |.  B8 F0604000   MOV EAX,OFFSET 004060F0   ; _RTERRCNT的地址这就是rterrs的地址了(就是在data段)
00401E40  |>  3B10                /CMP EDX,DWORD PTR DS:[EAX]    ; if ( rterrnum == rterrs[tblindx].rterrno )
00401E42  |.  74 0B               |JE SHORT 00401E4F                            ; break
00401E44  |.  83C0 08           |ADD EAX,8                                          
; 为什么加8, 因为 8 == sizeof(rterrmsgs)
00401E47  |.  41            |INC ECX        ; tblindx++

00401E48  |.  3D 80614000   |CMP EAX,OFFSET 00406180  ; 看有没有超过rterrs数组的范围
00401E4D  |.^ 72 F1         \JB SHORT 00401E40      ; 继续循环
                      ; 现在明白了 rterrs变量的地址是004060F0

                      ; rterrs数组项个数是 (00406180 - 004060F0) / 8 = 0x12 (18个)
00401E4F  |>  56            PUSH ESI

00401E50  |.  8BF1          MOV ESI,ECX

00401E52  |.  C1E6 03       SHL ESI,3

00401E55  |.  3B96 F0604000 CMP EDX,DWORD PTR DS:[ESI+4060F0]

00401E5B  |.  0F85 1C010000 JNE 00401F7D

00401E61  |.  A1 D8844000   MOV EAX,DWORD PTR DS:[4084D8]

00401E66  |.  83F8 01       CMP EAX,1

00401E69  |.  0F84 E8000000 JE 00401F57

00401E6F  |.  85C0          TEST EAX,EAX

00401E71  |.  75 0D         JNE SHORT 00401E80

00401E73  |.  833D 44604000 CMP DWORD PTR DS:[406044],1

00401E7A  |.  0F84 D7000000 JE 00401F57

00401E80  |>  81FA FC000000 CMP EDX,0FC

00401E86  |.  0F84 F1000000 JE 00401F7D

00401E8C  |.  8D85 5CFEFFFF LEA EAX,[LOCAL.105]

00401E92  |.  68 04010000   PUSH 104                                 ; /Count = 260.

00401E97  |.  50            PUSH EAX                                 ; |Buffer => OFFSET LOCAL.105

00401E98  |.  6A 00         PUSH 0                                   ; |hModule = NULL

00401E9A  |.  FF15 28504000 CALL DWORD PTR DS:[<&KERNEL32.GetModuleF ; \KERNEL32.GetModuleFileNameA

00401EA0  |.  85C0          TEST EAX,EAX

00401EA2  |.  75 13         JNE SHORT 00401EB7

00401EA4  |.  8D85 5CFEFFFF LEA EAX,[LOCAL.105]

00401EAA  |.  68 BC534000   PUSH OFFSET 004053BC                     ; ASCII "<program name unknown>"

00401EAF  |.  50            PUSH EAX

00401EB0  |.  E8 5B050000   CALL 00402410

00401EB5  |.  59            POP ECX

00401EB6  |.  59            POP ECX

00401EB7  |>  8D85 5CFEFFFF LEA EAX,[LOCAL.105]

00401EBD  |.  57            PUSH EDI

00401EBE  |.  50            PUSH EAX                                 ; /Arg1 => OFFSET LOCAL.105

00401EBF  |.  8DBD 5CFEFFFF LEA EDI,[LOCAL.105]                      ; |

00401EC5  |.  E8 F6060000   CALL 004025C0                            ; \AAAAAA.004025C0

00401ECA  |.  40            INC EAX                                  ; Switch (cases -1..3B, 2 exits)

00401ECB  |.  59            POP ECX

00401ECC  |.  83F8 3C       CMP EAX,3C

00401ECF  |.  76 29         JBE SHORT 00401EFA

00401ED1  |.  8D85 5CFEFFFF LEA EAX,[LOCAL.105]                      ; Default case of switch AAAAAA.401ECA

00401ED7  |.  50            PUSH EAX                                 ; /Arg1 => OFFSET LOCAL.105

00401ED8  |.  E8 E3060000   CALL 004025C0                            ; \AAAAAA.004025C0

00401EDD  |.  8BF8          MOV EDI,EAX

00401EDF  |.  8D85 5CFEFFFF LEA EAX,[LOCAL.105]

00401EE5  |.  83E8 3B       SUB EAX,3B

00401EE8  |.  6A 03         PUSH 3

00401EEA  |.  03F8          ADD EDI,EAX

00401EEC  |.  68 B8534000   PUSH OFFSET 004053B8                     ; ASCII "..."

00401EF1  |.  57            PUSH EDI

00401EF2  |.  E8 691D0000   CALL 00403C60

00401EF7  |.  83C4 10       ADD ESP,10

00401EFA  |>  8D85 60FFFFFF LEA EAX,[LOCAL.40]                       ; Cases -1, 0, .... 3B of switch AAAAAA....

                  ; (不明白这个干嘛)

00401F00  |.  68 9C534000   PUSH OFFSET 0040539C                     ; ASCII "Runtime Error!

Program: "

00401F05  |.  50            PUSH EAX

00401F06  |.  E8 05050000   CALL 00402410

00401F0B  |.  8D85 60FFFFFF LEA EAX,[LOCAL.40]

00401F11  |.  57            PUSH EDI

00401F12  |.  50            PUSH EAX

00401F13  |.  E8 08050000   CALL 00402420

00401F18  |.  8D85 60FFFFFF LEA EAX,[LOCAL.40]

00401F1E  |.  68 98534000   PUSH OFFSET 00405398                     ; ASCII "

"

00401F23  |.  50            PUSH EAX

00401F24  |.  E8 F7040000   CALL 00402420

00401F29  |.  FFB6 F4604000 PUSH DWORD PTR DS:[ESI+4060F4]           ; ASCII "HS@"

00401F2F  |.  8D85 60FFFFFF LEA EAX,[LOCAL.40]

00401F35  |.  50            PUSH EAX

00401F36  |.  E8 E5040000   CALL 00402420

00401F3B  |.  68 10200100   PUSH 12010

00401F40  |.  8D85 60FFFFFF LEA EAX,[LOCAL.40]

00401F46  |.  68 70534000   PUSH OFFSET 00405370                     ; ASCII "Microsoft Visual C++ Runtime Library"

00401F4B  |.  50            PUSH EAX

00401F4C  |.  E8 831C0000   CALL 00403BD4

00401F51  |.  83C4 2C       ADD ESP,2C

00401F54  |.  5F            POP EDI

00401F55  |.  EB 26         JMP SHORT 00401F7D

00401F57  |>  8D45 08       LEA EAX,[ARG.1]

00401F5A  |.  8DB6 F4604000 LEA ESI,[ESI+4060F4]                     ; ASCII "HS@"

00401F60  |.  6A 00         PUSH 0                                   ; /pOverlapped = NULL

00401F62  |.  50            PUSH EAX                                 ; |pBytesWritten => OFFSET ARG.1

00401F63  |.  FF36          PUSH DWORD PTR DS:[ESI]                  ; |/Arg1

00401F65  |.  E8 56060000   CALL 004025C0                            ; |\AAAAAA.004025C0

00401F6A  |.  59            POP ECX                                  ; |

00401F6B  |.  50            PUSH EAX                                 ; |Size

00401F6C  |.  FF36          PUSH DWORD PTR DS:[ESI]                  ; |Buffer

00401F6E  |.  6A F4         PUSH -0C                                 ; |/StdHandle = STD_ERROR_HANDLE

00401F70  |.  FF15 44504000 CALL DWORD PTR DS:[<&KERNEL32.GetStdHand ; |\KERNEL32.GetStdHandle

00401F76  |.  50            PUSH EAX                                 ; |hFile

00401F77  |.  FF15 64504000 CALL DWORD PTR DS:[<&KERNEL32.WriteFile> ; \KERNEL32.WriteFile

00401F7D  |>  5E            POP ESI

00401F7E  |.  C9            LEAVE

00401F7F  \.  C3            RETN
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息