乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      【原創(chuàng)】OllyDBG分析報告系列(4)

       herowuking 2015-05-31
      標 題: 【原創(chuàng)】OllyDBG分析報告系列(4)---獲得當前cpu狀態(tài)
      作 者: angelqkm
      時 間: 2008-05-25,22:48:25
      鏈 接: http://bbs./showthread.php?t=65476

      這是分析報告的第四部分,請多多指教。   

      Ollydbg(以下均簡稱為OD)中獲得當前cpu狀態(tài)的主要原理是:windows操作系統(tǒng)是多線程的操作系統(tǒng),其線程運行是分時間片的,每個程序按照其優(yōu)先級輪流運行一段時間。當運行一個線程時,其他線程需要把運行環(huán)境保留到一個地方,當時間片分配到自己時,再講運行環(huán)境讀取出來并運行。根據(jù)windows運行原理,調試寄存器能夠讀取、修改保存起來的線程運行環(huán)境,這樣也就獲得了CPU的工作狀態(tài)了。其API為:GetThreadContext、SetThreadContext。
      通過分析,OD會遍歷所有活動線程,得到其線程環(huán)境,并將得到的所有信息放到一個66Ch大小的結構體中,該結構體的詳細情況即該系一的int3斷點中提及的t_thread結構體。

      關于這部分的代碼分析,在IDA中已經詳細標出,就直接將IDA中的分析結果貼上。這里就總的說一下這個函數(shù)的功能以及參數(shù)(函數(shù)名為GetThreadInfo):
      a.  通過GetThreadContext的方法獲得線程的上下文環(huán)境,把該環(huán)境保存至OD線程信息結構中的reg字段中,若oldreg已經失效,則復制reg的值到oldreg中;
      b.  若被調試進程有多個線程,則循環(huán)取值,保存至OD線程信息結構數(shù)組中;
      c.  傳入?yún)?shù)為:DebugEvent.dwThreadId;
      d.  返回值為:成功時為保存在OD線程信息結構中的當前寄存器信息結構的指針(主線程),失敗返回0。

      GetThreadInfo   proc near               ; CODE XREF: sub_42EBD0+1A p
                                              ; _Suspendprocess+45 p

      reg_big[6]          = dword ptr -34h
      reg_seg_reg        = dword ptr -30h
      s_base_ss       = dword ptr -2Ch
      f_reg_st_i       = dword ptr -28h
      SelectorEntry   = _LDT_ENTRY ptr -24h
      ret             = dword ptr -1Ch
      pThreadInfo     = dword ptr -18h
      var_11          = byte ptr -11h
      src             = dword ptr -10h
      segment_size           = dword ptr -0Ch
      f_reg_index           = dword ptr -8
      i               = dword ptr -4
      ThreadId           = dword ptr  8

      保存現(xiàn)場,拉伸空間,檢查線程信息結構體是否存在,若不存在直接跳轉到結束處,若存在則跳過退出部分的代碼:
                      push    ebp
                      mov     ebp, esp
                      add     esp, 0FFFFFFCCh
                      mov     eax, pThreadInfo
                      push    ebx
                      push    esi
                      push    edi
                      mov     [ebp+pThreadInfo], eax
                      cmp     [ebp+pThreadInfo], 0
                      jnz     short has_ThreadInfo
                      xor     eax, eax
                      jmp     _exit
      ; ---------------------------------------------------------------------------
      下面開始即是一個大的循環(huán)體,這里初始值變量,然后跳轉到循環(huán)體的判斷處:
      has_ThreadInfo:                         ; CODE XREF: GetThreadInfo+15 j
                      xor     edx, edx
                      mov     [ebp+ret], edx
                      xor     ecx, ecx
                      mov     [ebp+i], ecx
                      jmp     loc_42E7C1
      ; ---------------------------------------------------------------------------
      這里開始為循環(huán)體的內部處理,即讀取當前cpu狀態(tài)到結構體中:
      getThreadInfo:                          ; CODE XREF: GetThreadInfo+37E j
      先將線程信息結構體中幾個標識修改狀態(tài)的值置零,即標識還沒有修改:
                      mov     eax, [ebp+pThreadInfo]
                      xor     edx, edx
                      mov     [eax+t_Thread.reg.modified], edx ; 標識寄存器是否修改
                      mov     ecx, [ebp+pThreadInfo]
                      xor     eax, eax
                      mov     [ecx+t_Thread.reg.modifiedbyuser], eax ; 標識被用戶修改
                      mov     edx, [ebp+pThreadInfo]
                      xor     ecx, ecx
                      mov     [edx+t_Thread.reg.singlestep], ecx ; 標識單步
      將CONTEXT結構體的ContextFlags設置為取得所有信息,然后調用GetThreadContext取當前線程信息,檢查是否取得線程信息,若取得則跳過錯誤處理,繼續(xù)設置:
                      mov     esi, [ebp+pThreadInfo]
                      add     esi, 20h
                      mov     dword ptr [esi], 1001Fh
                      push    esi             ; lpContext
                      mov     eax, [ebp+pThreadInfo]
                      mov     edx, [eax+t_Thread.thread] ; HANDLE  Thread handle
                      push    edx             ; hThread
                      call    GetThreadContext
                      test    eax, eax
                      jnz     short loc_42E4C7
      這里為沒有得到線程信息的處理,設置其線程信息有效值為0,即無效,然后跳轉到循環(huán)體判斷處遍歷下一個線程信息:
                      mov     ecx, [ebp+pThreadInfo]
                      xor     eax, eax
                      mov     [ecx+t_Thread.regvalid], eax ; int  Whether reg is valid
                      jmp     j_next_Thread
      ; ---------------------------------------------------------------------------
      檢查得到線程信息的線程ID是否與要得到線程的ID相同,若相同則設置返回值為其寄存器結構體的首地址,若不同則跳過對返回值的設置:
      loc_42E4C7:                             ; CODE XREF: GetThreadInfo+69 j
                      mov     eax, [ebp+pThreadInfo]
                      mov     ebx, [ebp+pThreadInfo]
                      add     ebx, 2ECh       ; ebx : ThreadInfo.reg
                      mov     edx, [eax]      ; edx : ThreadInfo.dwThreadId
                      cmp     edx, [ebp+ ThreadId]
                      jnz     short loc_42E4DD
                      mov     [ebp+ret], ebx
      下面將得到的線程信息結構體中 寄存器結構體的信息一一賦值到OD為其準備的線程信息結構體處:
      loc_42E4DD:                             ; CODE XREF: GetThreadInfo+8C j
                      mov     ecx, [esi+CONTEXT._Eax]
                      mov     [ebx+t_reg.r_eax], ecx ; ulong  register
                      mov     eax, [esi+CONTEXT._Ecx]
                      mov     [ebx+t_reg.r_ecx], eax ; ulong  register
                      mov     edx, [esi+CONTEXT._Edx]
                      mov     [ebx+t_reg.r_edx], edx ; ulong  register
                      mov     ecx, [esi+CONTEXT._Ebx]
                      mov     [ebx+t_reg.r_ebx], ecx ; ulong  register
                      mov     eax, [esi+CONTEXT._Esp]
                      mov     [ebx+t_reg.r_esp], eax ; ulong  register
                      mov     edx, [esi+CONTEXT._Ebp]
                      mov     [ebx+t_reg.r_ebp], edx ; ulong  register
                      mov     ecx, [esi+CONTEXT._Esi]
                      mov     [ebx+t_reg.r_esi], ecx ; ulong  register
                      mov     eax, [esi+CONTEXT._Edi]
                      mov     [ebx+t_reg.r_edi], eax ; ulong  register
                      mov     edx, [esi+CONTEXT._Eip]
                      mov     [ebx+t_reg.r_eip], edx ; ulong  Instruction pointer (EIP)
      初始化浮點寄存器的棧頂、狀態(tài)等變量:
                      lea     edx, [ebx+t_reg.f_reg_st0] ; long double  Float registers, f[top] - top of stack
                      mov     ecx, [esi+CONTEXT.EFlags]
                      mov     [ebx+t_reg.flags], ecx ; ulong  Flags
                      mov     eax, [esi+CONTEXT.FloatSave.StatusWord]
                      shr     eax, 0Bh
                      and     eax, 7
                      xor     edi, edi
                      mov     [ebx+t_reg.top], eax ; int  Index of top-of-stack
                      lea     eax, [ebx+t_reg.tag[8]] ; uchar  Float tags (0x3 - empty register)
                      mov     [ebp+s_base_ss], eax
                      mov     [ebp+f_reg_st_i], edx
      這段是循環(huán)遍歷8個浮點寄存器,對其檢查并進行賦值:
      loc_42E554:                             ; CODE XREF: GetThreadInfo+158 j
      8減去浮點寄存器的棧頂序號,再與80000007位與之后若為正則跳過對負數(shù)的處理,若為負數(shù)則取其補碼,由于浮點棧頂?shù)男蛱枮?,所以與80000007位與之后還是0,這里一個錯誤檢查:
                      lea     ecx, [edi+8]
                      sub     ecx, [ebx+t_reg.top] ; int  Index of top-of-stack
                      and     ecx, 80000007h
                      jns     short loc_42E567
                      dec     ecx
                      or      ecx, 0FFFFFFF8h
                      inc     ecx
      這里是一個循環(huán)體,根據(jù)序號給浮點寄存器結構體賦值,每個浮點寄存器10個字節(jié):
      loc_42E567:                             ; CODE XREF: GetThreadInfo+114 j
                      mov     [ebp+f_reg_index], ecx
                      mov     eax, [ebp+f_reg_st_i]
                      mov     edx, [ebp+f_reg_index]
                      lea     edx, [edx+edx*4]
                      mov     ecx, dword ptr [esi+edx*2+CONTEXT.FloatSave.RegisterArea]
                      mov     [eax], ecx
                      mov     ecx, dword ptr [esi+edx*2+(CONTEXT.FloatSave.RegisterArea+4)]
                      mov     [eax+4], ecx
                      mov     cx, word ptr [esi+edx*2+(CONTEXT.FloatSave.RegisterArea+8)]
                      mov     [eax+8], cx
      由于TagWord寄存器16位寬,只有一個作用,就是記錄每1個浮點寄存器的使用情況,8個浮點寄存器分為占用2位,所以每個寄存器有4個狀態(tài),分別為:00有效(Valid)、01零值(Zero)、10特殊的(Spical)、11空閑(Empty),這里就是按照序號標識其狀態(tài):
                      mov     ecx, edi
                      add     ecx, ecx
                      mov     eax, [esi+CONTEXT.FloatSave.TagWord]
                      shr     eax, cl
                      and     al, 3
                      mov     edx, [ebp+s_base_ss]
                      mov     [edx], al
      序號、寄存器基址、寄存器結構體指針自加,檢查是否遍歷完8個寄存器,若沒有遍歷完則繼續(xù):
                      inc     edi
                      inc     [ebp+s_base_ss]
                      add     [ebp+f_reg_st_i], 0Ah  ; 
                      cmp     edi, 8
                      jl      short loc_42E554
      最后設置控制字與狀態(tài)字寄存器:
                      mov     eax, [esi+CONTEXT.FloatSave.StatusWord]
                      xor     edi, edi
                      mov     [ebx+t_reg.fst], eax ; ulong  FPU status word
                      mov     edx, [esi+CONTEXT.FloatSave.ControlWord]
                      mov     [ebx+t_reg.fcw], edx ; ulong  FPU control word
      下面開始為對段寄存器的賦值,標識都已注明:
                      mov     ecx, [esi+CONTEXT.SegEs]
                      mov     [ebx+t_reg.s_reg_es], ecx ; ulong  Segment register
                      mov     eax, [esi+CONTEXT.SegCs]
                      mov     [ebx+t_reg.s_reg_cs], eax ; ulong  Segment register
                      mov     edx, [esi+CONTEXT.SegSs]
                      mov     [ebx+t_reg.s_reg_ss], edx ; ulong  Segment register
                      mov     ecx, [esi+CONTEXT.SegDs]
                      mov     [ebx+t_reg.s_reg_ds], ecx ; ulong  Segment register
                      mov     eax, [esi+CONTEXT.SegFs]
                      mov     [ebx+t_reg.s_reg_fs], eax ; ulong  Segment register
                      lea     eax, [ebx+t_reg.big[6]] ; uchar  Default size (0-16, 1-32 bit)
                      mov     edx, [esi+CONTEXT.SegGs]
                      mov     [ebx+t_reg.s_reg_gs], edx ; ulong  Segment register
      初始化段寄存器的兩個變量(size、segment_reg):
                      lea     edx, [ebx+t_reg.s_reg_es] ; ulong  Segment register
                      mov     [ebp+reg_big[6]], eax
                      mov     [ebp+reg_seg_reg], edx
      這段是循環(huán)遍歷6個段寄存器,得到其大小,放入reg_big[6]結構體中,即得到該段的大?。?br> loc_42E614:                             ; CODE XREF: GetThreadInfo+278 j
                      lea     ecx, [ebp+SelectorEntry]
                      push    ecx             ; lpSelectorEntry
                      mov     eax, [ebp+reg_seg_reg]
                      mov     edx, [eax]
                      push    edx             ; dwSelector
                      mov     ecx, [ebp+pThreadInfo]
                      mov     eax, [ecx+0Ch]
                      push    eax             ; hThread
                      call    GetThreadSelectorEntry    ; 取得當前線程描述符表
                      test    eax, eax
                      jz      short loc_42E697
                      movzx   ecx, [ebp+SelectorEntry.BaseLow]
                      mov     dl, byte ptr [ebp+SelectorEntry.HighWord]
                      mov     al, byte ptr [ebp+SelectorEntry.HighWord+3]
                      and     edx, 0FFh
                      and     eax, 0FFh
                      shl     edx, 10h
                      and     ecx, 0FFFFh
                      shl     eax, 18h
                      and     edx, 0FF0000h
                      add     edx, ecx
                      and     eax, 0FF000000h
                      add     edx, eax
                      mov     [ebp+segment_size], edx
                      movzx   edx, [ebp+SelectorEntry.LimitLow]
                      mov     al, byte ptr [ebp+SelectorEntry.HighWord+2]
                      and     edx, 0FFFFh
                      and     eax, 0Fh
                      shl     eax, 10h
                      and     eax, 0F0000h
                      add     eax, edx
                      test    byte ptr [ebp+SelectorEntry.HighWord+2], 80h
                      jz      short loc_42E689
                      shl     eax, 0Ch
                      add     eax, 0FFFh

      loc_42E689:                             ; CODE XREF: GetThreadInfo+233 j
                      mov     cl, byte ptr [ebp+SelectorEntry.HighWord+2]
                      shr     ecx, 6
                      and     ecx, 1
                      mov     [ebp+var_11], cl
                      jmp     short loc_42E6A2
      ; ---------------------------------------------------------------------------

      loc_42E697:                             ; CODE XREF: GetThreadInfo+1E0 j
                      xor     edx, edx
                      mov     eax, edx
                      mov     [ebp+segment_size], edx
                      mov     [ebp+var_11], 1

      loc_42E6A2:                             ; CODE XREF: GetThreadInfo+249 j
                      mov     ecx, [ebp+reg_seg_reg]
                      mov     edx, [ebp+segment_size]
                      mov     [ecx+18h], edx    ; reg_seg_reg + 18h 剛好是其對應的reg_big[6]所在的位置
                      mov     ecx, [ebp+reg_seg_reg]
                      mov     [ecx+30h], eax
                      mov     eax, [ebp+reg_big[6]]
                      mov     dl, [ebp+var_11]
                      mov     [eax], dl
      檢查6個段寄存器是否遍歷完畢,若完畢則退出循環(huán):
                      inc     edi
                      inc     [ebp+reg_big[6]]
                      add     [ebp+reg_seg_reg], 4
                      cmp     edi, 6
                      jl      loc_42E614
      下面是對調試寄存器的賦值:
                      mov     eax, [esi+CONTEXT.Dr0]
                      mov     [ebx+t_reg.drlin_dr0], eax ; ulong  Debug register
                      mov     ecx, [esi+CONTEXT.Dr1]
                      mov     [ebx+t_reg.drlin_dr1], ecx ; ulong  Debug register
                      mov     eax, [esi+CONTEXT.Dr2]
                      mov     [ebx+t_reg.drlin_dr2], eax ; ulong  Debug register
                      mov     edx, [esi+CONTEXT.Dr3]
                      mov     [ebx+t_reg.drlin_dr3], edx ; ulong  Debug register
                      mov     ecx, [esi+CONTEXT.Dr6]
                      mov     [ebx+t_reg.dr6], ecx ; ulong  Debug register DR6
                      mov     eax, [esi+CONTEXT.Dr7]
                      mov     [ebx+t_reg.dr7], eax ; ulong  Debug register DR7
                      mov     edx, [ebp+arg_0]
                      mov     [ebx+t_reg.threadid], edx ; ulong  ID of thread that owns registers
                      mov     eax, VersionInformation.dwPlatformId
      檢查子系統(tǒng)屬性,根據(jù)其進行相應的設置:
                      cmp     eax, 2      ; 檢查是否是windows圖形界面
                      jnz     short loc_42E71A
                      mov     eax, 34h      ; 若是則使 EAX = 34h
                      jmp     short loc_42E728
      ; ---------------------------------------------------------------------------

      loc_42E71A:                             ; CODE XREF: GetThreadInfo+2C5 j
                      cmp     eax, 1      ; 檢查是否為本地屬性
                      jnz     short loc_42E726
                      mov     eax, 60h      ; 若是則使EAX = 60h
                      jmp     short loc_42E728
      ; ---------------------------------------------------------------------------

      loc_42E726:                             ; CODE XREF: GetThreadInfo+2D1 j
                      xor     eax, eax      ; 若都不是則設置EAX = 0

      loc_42E728:                             ; CODE XREF: GetThreadInfo+2CC j
                                              ; GetThreadInfo+2D8 j
                      test    eax, eax
                      jz      short loc_42E75C
                      cmp     dword_4D579C, 0
                      jz      short loc_42E75C
                      push    3               ; char
                      push    4               ; n
                      mov     edx, [ebp+pThreadInfo]
                      add     eax, [edx+t_Thread.datablock] ; ulong  Per-thread data block
                      push    eax             ; arglist
                      lea     ecx, [ebp+src]
                      push    ecx             ; src
                      call    _Readmemory
                      add     esp, 10h
                      cmp     eax, 4
                      jnz     short loc_42E75C
                      mov     eax, [ebp+src]
                      mov     [ebx+0EEh], eax
                      jmp     short loc_42E766
      ; ---------------------------------------------------------------------------

      loc_42E75C:                             ; CODE XREF: GetThreadInfo+2DE j
                                              ; GetThreadInfo+2E7 j ...
                      mov     dword ptr [ebx+0EEh], 0FFFFFFFFh
      將剛得到的寄存器信息設置為有效,并檢查線程信息結構體中oldreg的屬性是否有效,若無效則將當前的寄存器值賦值進去:
      loc_42E766:                             ; CODE XREF: GetThreadInfo+30E j
                      xor     edx, edx
                      xor     ecx, ecx
                      mov     [ebx+0F2h], edx
                      mov     [ebx+0F6h], ecx
                      mov     eax, [ebp+pThreadInfo]
                      mov     [eax+t_Thread.regvalid], 1 ; int  Whether reg is valid
                      mov     edx, [ebp+pThreadInfo]
                      cmp     dword ptr [edx+t_Thread.oldregvalid], 0 ; check ThreadInfo is read
                      jnz     short j_next_Thread
                      mov     ecx, [ebp+pThreadInfo]
                      mov     eax, [ebp+pThreadInfo]
                      lea     esi, [ecx+t_Thread.reg] ; struct  Actual contents of registers
                      lea     edi, [eax+t_Thread.oldreg] ; struct  Previous contents of registers
                      mov     ecx, 65h
                      rep movsd               ; Thread.reg copy to Thread.oldreg
                      movsw
                      mov     eax, [ebp+pThreadInfo]
                      mov     dword ptr [eax+61Ch], 1
      將線程計數(shù)自加1,將線程信息結構體指針指向下一個結構體的首地址(ThreadInfo的大小為66Ch):
      j_next_Thread:                          ; CODE XREF: GetThreadInfo+76 j
                                              ; GetThreadInfo+341 j
                      inc     [ebp+i]
                      add     [ebp+pThreadInfo], 66Ch ; pThreadInfo -> next ThreadInfo
      這里為循環(huán)體的判斷處,檢查是否遍歷完所有線程,若沒有遍歷完,則繼續(xù)遍歷:
      loc_42E7C1:                             ; CODE XREF: GetThreadInfo+28 j
                      mov     edx, [ebp+i]
                      cmp     edx, Num_Thread
                      jl      getThreadInfo
                      mov     eax, [ebp+ret]
      最后恢復現(xiàn)場:
      _exit:                                  ; CODE XREF: GetThreadInfo+19 j
                      pop     edi
                      pop     esi
                      pop     ebx
                      mov     esp, ebp
                      pop     ebp
                      retn
      GetThreadInfo   endp
                                    武漢科銳學員: angelqkm
                                      2008-5-25                                 

        本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
        轉藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多