VC6启动代码分析

      好久没写技术文章了,可见最近生活如此颓废。。。。。。嘿嘿……为了工作方便,分析了下VC6的启动代码,扔上来充个数,原程序在VC98/CRT/SRC/CRT0.C这个文件中。
      须分析的程序名:a.cpp
      编译器:VC6
      编译环境:进入console,在VC98/Bin,运行VCVARS32.BAT,环境设置好,然后运行cl a.cpp
 
      分析前准备:
      由于CRT0.C这个文件中用到了VC中  __try{...}__except(...){...} 处理了下异常,咱不熟,就得先熟悉这个结构编译的结果。
      分析程序:
/   CUT HERE  /
/* b.cpp */ 

01  #include "stdio.h"
02  
03  void main()
04  {
05     int* p = 0x00000000;   // pointer to NULL
06     puts("hello");
07     __try{
08        puts("in try");
09  //      try{
10  //         puts("in try");
11  //         *p = 13;    // causes an access violation exception;
12  //      }__finally{
13  //         puts("in finally");
14  //      }
15     }__except(puts("in filter"), 1){
16        puts("in except");
17     }
18     puts("world");
19  }

///  CUT END ///

编译后,生成的结果(偶只调重要的贴上来)

.text:00401000                   ; int __cdecl main(int argc,const char **argv,const char *envp)
.text:00401000                   _main           proc near               ; CODE XREF: start+AFp
.text:00401000
.text:00401000                   var_1C          = dword ptr -1Ch
.text:00401000                   var_18          = dword ptr -18h
.text:00401000                   var_10          = dword ptr -10h
.text:00401000                   var_4            = dword ptr -4
.text:00401000                   argc              = dword ptr  8
.text:00401000                   argv              = dword ptr  0Ch
.text:00401000                   envp             = dword ptr  10h
.text:00401000
.text:00401000 55                                push    ebp
.text:00401001 8B EC                             mov     ebp, esp
.text:00401003 6A FF                             push    0FFFFFFFFh
.text:00401005 68 B0 60 40 00                    push    offset dword_4060B0
.text:0040100A 68 00 12 40 00                    push    offset unknown_libname_1 ; Microsoft VisualC 2-7/net runtime
.text:0040100F 64 A1 00 00 00 00                 mov     eax, large fs:0
.text:00401015 50                                push    eax
.text:00401016 64 89 25 00 00 00+                mov     large fs:0, esp
.text:0040101D 83 C4 F4                          add     esp, 0FFFFFFF4h
.text:00401020 53                                push    ebx
.text:00401021 56                                push    esi
.text:00401022 57                                push    edi
.text:00401023 89 65 E8                          mov     [ebp+var_18], esp
.text:00401026 C7 45 E4 00 00 00+                mov     [ebp+var_1C], 0
.text:0040102D 68 30 70 40 00                    push    offset aHello   ; "hello"
.text:00401032 E8 68 00 00 00                    call    _puts
.text:00401037 83 C4 04                          add     esp, 4
.text:0040103A C7 45 FC 00 00 00+                mov     [ebp+var_4], 0
.text:00401041 68 38 70 40 00                    push    offset aInTry   ; "in try"
.text:00401046 E8 54 00 00 00                    call    _puts
.text:0040104B 83 C4 04                          add     esp, 4
.text:0040104E C7 45 FC FF FF FF+                mov     [ebp+var_4], 0FFFFFFFFh
.text:00401055 EB 2A                             jmp     short loc_401081
.text:00401057                   ; ?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥
.text:00401057
.text:00401057                   __except:                               ; DATA XREF: .rdata:004060B4o
.text:00401057 68 40 70 40 00                    push    offset aInFilter ; "in filter"
.text:0040105C E8 3E 00 00 00                    call    _puts
.text:00401061 83 C4 04                          add     esp, 4
.text:00401064 B8 01 00 00 00                    mov     eax, 1
.text:00401069 C3                                retn
.text:0040106A                   ; ?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥
.text:0040106A
.text:0040106A                   __except_body:
.text:0040106A 8B 65 E8                          mov     esp, [ebp-18h]
.text:0040106D 68 4C 70 40 00                    push    offset aInExcept ; "in except"
.text:00401072 E8 28 00 00 00                    call    _puts
.text:00401077 83 C4 04                          add     esp, 4
.text:0040107A C7 45 FC FF FF FF+                mov     [ebp+var_4], 0FFFFFFFFh
.text:00401081
.text:00401081                   loc_401081:                             ; CODE XREF: _main+55j
.text:00401081 68 58 70 40 00                    push    offset aWorld   ; "world"
.text:00401086 E8 14 00 00 00                    call    _puts
.text:0040108B 83 C4 04                          add     esp, 4
.text:0040108E 8B 4D F0                          mov     ecx, [ebp+var_10]
.text:00401091 64 89 0D 00 00 00+                mov     large fs:0, ecx
.text:00401098 5F                                pop     edi
.text:00401099 5E                                pop     esi
.text:0040109A 5B                                pop     ebx
.text:0040109B 8B E5                             mov     esp, ebp
.text:0040109D 5D                                pop     ebp
.text:0040109E C3                                retn
.text:0040109E                   _main           endp
注意,是怎么处理异常的!

开始几句

.text:00401005 68 B0 60 40 00                    push    offset dword_4060B0
.text:0040100A 68 00 12 40 00                    push    offset unknown_libname_1 ; Microsoft VisualC 2-7/net runtime
.text:0040100F 64 A1 00 00 00 00                 mov     eax, large fs:0
.text:00401015 50                                push    eax
.text:00401016 64 89 25 00 00 00+                mov     large fs:0, esp
是设置异常的,奇怪的是,似乎每个__try{...} __except(...){...} 结构,都是push offset unknown_libname_1的。。。不管了,起码偶分析的两个是如此出来,改天分析正常的cpp异常结构再说。

看到 push offset dword_4060B0 跟进去瞧瞧

.rdata:004060B0 FF FF FF FF       dword_4060B0    dd 0FFFFFFFFh           ; DATA XREF: _main+5o
.rdata:004060B4 57 10 40 00                       dd offset __except

shit!敲明白否? 那个__except是偶注释的,敲机器码,可见实际抵制是401057h

也就是,在_main函数内,明白否?

偶这实际注释的,就是

__except,是处理捕捉的函数的,也就是__except(...)括号中的

__except_body,才是,实际处理异常的程序,也就是__excpet(...){...},大括号中的。

 

有了此基础,分析程序CRT0.C文件

/  CUT  HERE   ///

001  /***
002  *crt0.c - C runtime initialization routine
003  *
004  *       Copyright (c) 1989-1997, Microsoft Corporation. All rights reserved.
005  *
006  *Purpose:
007  *       This the actual startup routine for apps.  It calls the user's main
008  *       routine [w]main() or [w]WinMain after performing C Run-Time Library
009  *       initialization.
010  *
011  *       (With ifdef's, this source file also provides the source code for
012  *       wcrt0.c, the startup routine for console apps with wide characters,
013  *       wincrt0.c, the startup routine for Windows apps, and wwincrt0.c,
014  *       the startup routine for Windows apps with wide characters.)
015  *
016  *******************************************************************************/

017  
018  #ifdef _WIN32
019  
020  #ifndef CRTDLL
021  
022  #include <cruntime.h>
023  #include <dos.h>
024  #include <internal.h>
025  #include <stdlib.h>
026  #include <string.h>
027  #include <rterr.h>
028  #include <windows.h>
029  #include <awint.h>
030  #include <tchar.h>
031  #include <dbgint.h>
032  
033  /*
034   * wWinMain is not yet defined in winbase.h. When it is, this should be
035   * removed.
036   */

037  
038  int
039  WINAPI
040  wWinMain(
041      HINSTANCE hInstance,
042      HINSTANCE hPrevInstance,
043      LPWSTR lpCmdLine,
044      int nShowCmd
045      );
046  
047  #ifdef WPRFLAG
048  _TUCHAR * __cdecl _wwincmdln(void);
049  #else  /* WPRFLAG */
050  _TUCHAR * __cdecl _wincmdln(void);
051  #endif  /* WPRFLAG */
052  
053  /*
054   * command line, environment, and a few other globals
055   */

056  
057  #ifdef WPRFLAG
058  wchar_t *_wcmdln;           /* points to wide command line */
059  #else  /* WPRFLAG */
060  char *_acmdln;              /* points to command line */
061  #endif  /* WPRFLAG */
062  
063  char *_aenvptr = NULL;      /* points to environment block */
064  wchar_t *_wenvptr = NULL;   /* points to wide environment block */
065  
066  
067  void (__cdecl * _aexit_rtn)(int) = _exit;   /* RT message return procedure */
068  
069  static void __cdecl fast_error_exit(int);   /* Error exit via ExitProcess */
070  
071  /*
072   * _error_mode and _apptype, together, determine how error messages are
073   * written out.
074   */

075  int __error_mode = _OUT_TO_DEFAULT;
076  #ifdef _WINMAIN_
077  int __app_type = _GUI_APP;
078  #else  /* _WINMAIN_ */
079  int __app_type = _CONSOLE_APP;
080  #endif  /* _WINMAIN_ */
081  
082  
083  /***
084  *BaseProcessStartup(PVOID Peb)
085  *
086  *Purpose:
087  *       This routine does the C runtime initialization, calls main(), and
088  *       then exits.  It never returns.
089  *
090  *Entry:
091  *       PVOID Peb - pointer to Win32 Process Environment Block (not used)
092  *
093  *Exit:
094  *       This function never returns.
095  *
096  *******************************************************************************/

097  
098  #ifdef _WINMAIN_
099  
100  #ifdef WPRFLAG
101  void wWinMainCRTStartup(
102  #else  /* WPRFLAG */
103  void WinMainCRTStartup(
104  #endif  /* WPRFLAG */
105  
106  #else  /* _WINMAIN_ */
107  
108  #ifdef WPRFLAG
109  void wmainCRTStartup(
110  #else  /* WPRFLAG */
111  void mainCRTStartup(
112  #endif  /* WPRFLAG */
113  
114  #endif  /* _WINMAIN_ */
115          void
116          )
117  // 根据编译器的设置,选择出实际使用的
118  // void wWinMainCRTStartup(void)
119  // void WinMainCRTStartup(void)
120  // wmainCRTStartup(void)
121  // mainCRTStartup(void)
122  {
123          int mainret;
124  
125  #ifdef _WINMAIN_
126          _TUCHAR *lpszCommandLine;
127          STARTUPINFO StartupInfo;
128  #endif  /* _WINMAIN_ */
129  
130          /*
131           * Get the full Win32 version
132           */

133          // 获得版本信息
134          _osver = GetVersion();
135  
136          _winminor = (_osver >> 8) & 0x00FF ;
137          _winmajor = _osver & 0x00FF ;
138          _winver = (_winmajor << 8) + _winminor;
139          _osver = (_osver >> 16) & 0x00FFFF ;
140  
141  //  静态库版本:
142  //  /ML Single-Threaded 使用静态库LIBC.LIB 
143  //  /MLd Debug Single-Threaded 使用静态库LIBCD.LIB
144  //  /MT Multithreaded 使用静态库LIBCMT.LIB
145  //  /MTd Debug Multithreaded 使用静态库LIBCMTD.LIB
146  #ifdef _MT
147          if ( !_heap_init(1) )               /* initialize heap */  // 多线程用此方式初始化堆
148  #else  /* _MT */
149          if ( !_heap_init(0) )               /* initialize heap */  // 单线程用此方式初始化堆 
150  #endif  /* _MT */
151              fast_error_exit(_RT_HEAPINIT);  /* write message and die */
152  
153  #ifdef _MT
154          if( !_mtinit() )                    /* initialize multi-thread */
155              fast_error_exit(_RT_THREAD);    /* write message and die */
156  #endif  /* _MT */
157  
158          /*
159           * Guard the remainder of the initialization code and the call
160           * to user's main, or WinMain, function in a __try/__except
161           * statement.
162           */

163  
164          __try {
165  
166              _ioinit();                      /* initialize lowio */
167  
168  #ifdef WPRFLAG
169              /* get wide cmd line info */
170              _wcmdln = (wchar_t *)__crtGetCommandLineW();
171  
172              /* get wide environ info */
173              _wenvptr = (wchar_t *)__crtGetEnvironmentStringsW();
174  
175              _wsetargv();
176              _wsetenvp();
177  #else  /* WPRFLAG */
178              /* get cmd line info */
179              _acmdln = (char *)GetCommandLineA();
180  
181              /* get environ info */
182              _aenvptr = (char *)__crtGetEnvironmentStringsA();
183  
184              _setargv();
185              _setenvp();
186  #endif  /* WPRFLAG */
187  
188              _cinit();                       /* do C data initialize */
189  
190  #ifdef _WINMAIN_
191  
192              StartupInfo.dwFlags = 0;
193              GetStartupInfo( &StartupInfo );
194  
195  #ifdef WPRFLAG
196              lpszCommandLine = _wwincmdln();
197              mainret = wWinMain(
198  #else  /* WPRFLAG */
199              lpszCommandLine = _wincmdln();
200              mainret = WinMain(
201  #endif  /* WPRFLAG */
202                                 GetModuleHandleA(NULL),
203                                 NULL,
204                                 lpszCommandLine,
205                                 StartupInfo.dwFlags & STARTF_USESHOWWINDOW
206                                      ? StartupInfo.wShowWindow
207                                      : SW_SHOWDEFAULT
208                               );
209  #else  /* _WINMAIN_ */
210  
211  #ifdef WPRFLAG
212              __winitenv = _wenviron;
213              mainret = wmain(__argc, __wargv, _wenviron);
214  #else  /* WPRFLAG */
215              __initenv = _environ;
216              mainret = main(__argc, __argv, _environ);
217  #endif  /* WPRFLAG */
218  
219  #endif  /* _WINMAIN_ */
220              exit(mainret);
221          }
222          __except ( _XcptFilter(GetExceptionCode(), GetExceptionInformation()) )
223          {
224              /*
225               * Should never reach here
226               */

227              _exit( GetExceptionCode() );
228  
229          } /* end of try - except */
230  
231  }
232  
233  
234  
235  /***
236  *_amsg_exit(rterrnum) - Fast exit fatal errors
237  *
238  *Purpose:
239  *       Exit the program with error code of 255 and appropriate error
240  *       message.
241  *
242  *Entry:
243  *       int rterrnum - error message number (amsg_exit only).
244  *
245  *Exit:
246  *       Calls exit() (for integer divide-by-0) or _exit() indirectly
247  *       through _aexit_rtn [amsg_exit].
248  *       For multi-thread: calls _exit() function
249  *
250  *Exceptions:
251  *
252  *******************************************************************************/

253  
254  void __cdecl _amsg_exit (
255          int rterrnum
256          )
257  {
258  #ifdef _WINMAIN_
259          if ( __error_mode == _OUT_TO_STDERR )
260  #else  /* _WINMAIN_ */
261          if ( __error_mode != _OUT_TO_MSGBOX )
262  #endif  /* _WINMAIN_ */
263              _FF_MSGBANNER();    /* write run-time error banner */
264  
265          _NMSG_WRITE(rterrnum);  /* write message */
266          _aexit_rtn(255);        /* normally _exit(255) */
267  }
268  
269  /***
270  *fast_error_exit(rterrnum) - Faster exit fatal errors
271  *
272  *Purpose:
273  *       Exit the process with error code of 255 and appropriate error
274  *       message.
275  *
276  *Entry:
277  *       int rterrnum - error message number (amsg_exit only).
278  *
279  *Exit:
280  *       Calls ExitProcess.
281  *
282  *Exceptions:
283  *
284  *******************************************************************************/

285  
286  static void __cdecl fast_error_exit (
287          int rterrnum
288          )
289  {
290  #ifdef _WINMAIN_
291          if ( __error_mode == _OUT_TO_STDERR )
292  #else  /* _WINMAIN_ */
293          if ( __error_mode != _OUT_TO_MSGBOX )
294  #endif  /* _WINMAIN_ */
295              _FF_MSGBANNER();    /* write run-time error banner */
296  
297          _NMSG_WRITE(rterrnum);  /* write message */
298          ExitProcess(255);       /* normally _exit(255) */
299  }
300  
301  #ifndef WPRFLAG
302  
303  
304  #endif  /* WPRFLAG */
305  
306  #endif  /* CRTDLL */
307  
308  #else  /* _WIN32 */
309  
/ CUT END //

知道了__try{...}  __except(...){...} j结果,在分析这个程序,就比较简单了

瞧瞧欲分析的例子程序

01  ///   CUT HERE ///
02  // a.cpp //
03  #include <stdio.h>
04  
05  int main()
06  {
07          return 0;
08  }
09  //    CUT END  //

很简单,看看分析结果

.text:00401007                                   public start
.text:00401007                   start           proc near
.text:00401007
.text:00401007                   var_20          = dword ptr -20h
.text:00401007                   var_1C          = dword ptr -1Ch
.text:00401007                   var_18          = dword ptr -18h
.text:00401007                   ExceptionInfo   = dword ptr -14h
.text:00401007                   var_4           = dword ptr -4
.text:00401007
.text:00401007 55                                push    ebp
.text:00401008 8B EC                             mov     ebp, esp
.text:0040100A 6A FF                             push    0FFFFFFFFh
.text:0040100C 68 A0 50 40 00                    push    offset dword_4050A0
.text:00401011 68 64 1C 40 00                    push    offset unknown_libname_1 ; Microsoft VisualC 2-7/net runtime
.text:00401016 64 A1 00 00 00 00                 mov     eax, large fs:0
.text:0040101C 50                                push    eax
.text:0040101D 64 89 25 00 00 00+                mov     large fs:0, esp
.text:00401024 83 EC 10                          sub     esp, 10h
.text:00401027 53                                push    ebx
.text:00401028 56                                push    esi
.text:00401029 57                                push    edi
.text:0040102A 89 65 E8                          mov     [ebp+var_18], esp
.text:0040102D FF 15 04 50 40 00                 call    ds:GetVersion   ; Get current version number of Windows
.text:0040102D                                                           ; and information about the operating system platform
.text:00401033 33 D2                             xor     edx, edx
.text:00401035 8A D4                             mov     dl, ah
.text:00401037 89 15 E4 84 40 00                 mov     dword_4084E4, edx
.text:0040103D 8B C8                             mov     ecx, eax
.text:0040103F 81 E1 FF 00 00 00                 and     ecx, 0FFh
.text:00401045 89 0D E0 84 40 00                 mov     dword_4084E0, ecx
.text:0040104B C1 E1 08                          shl     ecx, 8
.text:0040104E 03 CA                             add     ecx, edx
.text:00401050 89 0D DC 84 40 00                 mov     dword_4084DC, ecx
.text:00401056 C1 E8 10                          shr     eax, 10h
.text:00401059 A3 D8 84 40 00                    mov     dword_4084D8, eax
.text:0040105E 6A 00                             push    0
.text:00401060 E8 A8 0A 00 00                    call    _heap_init
.text:00401065 59                                pop     ecx
.text:00401066 85 C0                             test    eax, eax
.text:00401068 75 08                             jnz     short loc_401072
.text:0040106A 6A 1C                             push    1Ch             ; NumberOfBytesWritten
.text:0040106C E8 9A 00 00 00                    call    _fast_error_exit
.text:00401071 59                                pop     ecx
.text:00401072
.text:00401072                   loc_401072:                             ; CODE XREF: start+61j
.text:00401072 83 65 FC 00                       and     [ebp+var_4], 0
.text:00401076 E8 72 07 00 00                    call    __ioinit
.text:0040107B FF 15 00 50 40 00                 call    ds:GetCommandLineA
.text:00401081 A3 D8 89 40 00                    mov     dword_4089D8, eax
.text:00401086 E8 30 06 00 00                    call    ___crtGetEnvironmentStringsA
.text:0040108B A3 C0 84 40 00                    mov     dword_4084C0, eax
.text:00401090 E8 D9 03 00 00                    call    __setargv
.text:00401095 E8 1B 03 00 00                    call    __setenvp
.text:0040109A E8 90 00 00 00                    call    __cinit
.text:0040109F A1 F4 84 40 00                    mov     eax, envp
.text:004010A4 A3 F8 84 40 00                    mov     dword_4084F8, eax
.text:004010A9 50                                push    eax             ; envp
.text:004010AA FF 35 EC 84 40 00                 push    argv            ; argv
.text:004010B0 FF 35 E8 84 40 00                 push    argc            ; argc
.text:004010B6 E8 45 FF FF FF                    call    _main
.text:004010BB 83 C4 0C                          add     esp, 0Ch
.text:004010BE 89 45 E4                          mov     [ebp+var_1C], eax
.text:004010C1 50                                push    eax             ; int
.text:004010C2 E8 95 00 00 00                    call    _exit
.text:004010C7                   ; ?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥
.text:004010C7
.text:004010C7                   __except:                               ; DATA XREF: .rdata:004050A4o
.text:004010C7 8B 45 EC                          mov     eax, [ebp+ExceptionInfo]
.text:004010CA 8B 08                             mov     ecx, [eax]
.text:004010CC 8B 09                             mov     ecx, [ecx]
.text:004010CE 89 4D E0                          mov     [ebp+var_20], ecx
.text:004010D1 50                                push    eax             ; ExceptionInfo
.text:004010D2 51                                push    ecx             ; int
.text:004010D3 E8 59 01 00 00                    call    __XcptFilter
.text:004010D8 59                                pop     ecx
.text:004010D9 59                                pop     ecx
.text:004010DA C3                                retn
.text:004010DB                   ; ?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥?¥
.text:004010DB
.text:004010DB                   __except_body:
.text:004010DB 8B 65 E8                          mov     esp, [ebp+var_18]
.text:004010DE FF 75 E0                          push    [ebp+var_20]    ; int
.text:004010E1 E8 87 00 00 00                    call    __exit
.text:004010E1                   start           endp

这就是启动的整体部分,嘿嘿,很明显了吧,对这CRT0.C文件看~~

注意,IDA分析的有点问题,主要是针对start这个函数的结尾分析有问题

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值