• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            tqsheng

            go.....
            隨筆 - 366, 文章 - 18, 評論 - 101, 引用 - 0
            數據加載中……

            http://bbs.pcpop.com/080119/0O00560O000009621-1.html

            http://bbs.pcpop.com/080119/0O00560O000009621-1.html

            posted @ 2009-03-16 17:04 tqsheng 閱讀(403) | 評論 (1)編輯 收藏

            http://qzone.qq.com/blog/3484871-1226909513

            http://qzone.qq.com/blog/3484871-1226909513
            http://www.yoobao.net/redirect.php?tid=9696&goto=lastpost
            http://bbs.cnsmartphone.com/thread-27080-1-1.html

            http://cn.made-in-china.com/image/4f0j01yBeEiJvhEpqtM/%E6%97%A5%E6%9C%ACMAXELL%E7%BA%BD%E6%89%A3%E7%94%B5%E6%B1%A0%EF%BC%88ML2016%EF%BC%89.jpg

            posted @ 2009-03-11 12:54 tqsheng 閱讀(180) | 評論 (0)編輯 收藏

            http://bible.younet.com/files/2005/12/17/332810.shtml

            http://bible.younet.com/files/2005/12/17/332810.shtml

            http://www.dpdbbs.com/thread-74895-1-1.html

            登錄名

            1acer

            密碼123456

            posted @ 2009-03-05 08:50 tqsheng 閱讀(187) | 評論 (0)編輯 收藏

            TLS callback科普小知識

            TLS callback科普小知識
            2008年04月29日 星期二 下午 01:47
            前言:最初想了解TLS callback是來自于team509翻譯的一篇關于TLS callback反ida的文章。當時問了幾個朋友對TLS callback都不太了解,但是問到dummy牛,他給了一個他曾經寫過的使用TLS callback anti-debugger的殼,于是就看了下TLS callback機制。如果你是新手,并對TLS callback機制感興趣,那么這篇基礎文章也許對你有用。不過,了解的就勿看了,沒有什么東西 :)。另外,文章沒有進行排版修改.....= =|||

            ======================我是邪惡的分割線=========================

            每個線程擁有自己的線程局部存儲,互補干擾。系統中線程局部存儲是存放在線程的TEB中,每個線程都有自己的TEB因此互相獨立。見下面的TEB結構中的ThreadLocalStoragePointer、TlsSlots、TlsLinksTlsExpansionSlots域。對TLS的訪問通過 TlsAlloc、TlsSetValue和TlsGetValue以及TlsFree幾個API進行。這些API也是對TEB中Tls相關域的訪問。跟蹤Tls*等API函數發現,系統通過PEB中的TlsBitmap來保存Tls的使用記錄,并據此分配Tls索引,另外PEB還有 TlsExpansionCounter和TlsBitmapBits來跟蹤Tls的使用情況。

            選擇子fs所對應的段用來存儲TEB和PEB等信息,由ring3下FS選擇子如下:
            selector 3B, DATA32, BaseAddress 7FFDF000, Limit 00000FFF, DPL 3, Present, RW
            因此在ring3下是可讀寫的。fs:[0]指向_NT_TIB中的ExceptionList,fs:[18]指向_NT_TIB自身,也就是指向_TEB結構;
            mov eax, dword ptr fs:[18]
            mov esi, dword ptr [eax+30]
            此時esi指向PEB,dword ptr[esi+40]即為TlsBitmap,假設ecx為分配的索引則

            mov eax, dword ptr fs:[18]
            mov [eax+ecx*4+e10], data

            mov eax, dword ptr fs:[18]
            mov data, [eax+ecx*4+e10]

            結構如下所示(windows XP professional SP2)

                kd> dt !_NT_TIB
                +0×000 ExceptionList : Ptr32 _EXCEPTION_REGISTRATION_RECORD
                +0×004 StackBase : Ptr32 Void
                +0×008 StackLimit : Ptr32 Void
                +0×00c SubSystemTib : Ptr32 Void
                +0×010 FiberData : Ptr32 Void
                +0×010 Version : Uint4B
                +0×014 ArbitraryUserPointer : Ptr32 Void
                +0×018 Self : Ptr32 _NT_TIB
                //SEH和棧信息

                kd> dt !_TEB
                +0×000 NtTib : _NT_TIB
                +0×01c EnvironmentPointer : Ptr32 Void
                +0×020 ClientId : _CLIENT_ID
                +0×028 ActiveRpcHandle : Ptr32 Void
                +0×02c ThreadLocalStoragePointer : Ptr32 Void
                +0×030 ProcessEnvironmentBlock : Ptr32 _PEB
                +0×034 LastErrorValue : Uint4B
                +0×038 CountOfOwnedCriticalSections : Uint4B
                +0×03c CsrClientThread : Ptr32 Void
                +0×040 Win32ThreadInfo : Ptr32 Void
                +0×044 User32Reserved : [26] Uint4B
                +0×0ac UserReserved : [5] Uint4B
                +0×0c0 WOW32Reserved : Ptr32 Void
                +0×0c4 CurrentLocale : Uint4B
                +0×0c8 FpSoftwareStatusRegister : Uint4B
                +0×0cc SystemReserved1 : [54] Ptr32 Void
                +0×1a4 ExceptionCode : Int4B
                +0×1a8 ActivationContextStack : _ACTIVATION_CONTEXT_STACK
                +0×1bc SpareBytes1 : [24] UChar
                +0×1d4 GdiTebBatch : _GDI_TEB_BATCH
                +0×6b4 RealClientId : _CLIENT_ID
                +0×6bc GdiCachedProcessHandle : Ptr32 Void
                +0×6c0 GdiClientPID : Uint4B
                +0×6c4 GdiClientTID : Uint4B
                +0×6c8 GdiThreadLocalInfo : Ptr32 Void
                +0×6cc Win32ClientInfo : [62] Uint4B
                +0×7c4 glDispatchTable : [233] Ptr32 Void
                +0xb68 glReserved1 : [29] Uint4B
                +0xbdc glReserved2 : Ptr32 Void
                +0xbe0 glSectionInfo : Ptr32 Void
                +0xbe4 glSection : Ptr32 Void
                +0xbe8 glTable : Ptr32 Void
                +0xbec glCurrentRC : Ptr32 Void
                +0xbf0 glContext : Ptr32 Void
                +0xbf4 LastStatusValue : Uint4B
                +0xbf8 StaticUnicodeString : _UNICODE_STRING
                +0xc00 StaticUnicodeBuffer : [261] Uint2B
                +0xe0c DeallocationStack : Ptr32 Void
                +0xe10 TlsSlots : [64] Ptr32 Void
                +0xf10 TlsLinks : _LIST_ENTRY
                +0xf18 Vdm : Ptr32 Void
                +0xf1c ReservedForNtRpc : Ptr32 Void
                +0xf20 DbgSsReserved : [2] Ptr32 Void
                +0xf28 HardErrorsAreDisabled : Uint4B
                +0xf2c Instrumentation : [16] Ptr32 Void
                +0xf6c WinSockData : Ptr32 Void
                +0xf70 GdiBatchCount : Uint4B
                +0xf74 InDbgPrint : UChar
                +0xf75 FreeStackOnTermination : UChar
                +0xf76 HasFiberData : UChar
                +0xf77 IdealProcessor : UChar
                +0xf78 Spare3 : Uint4B
                +0xf7c ReservedForPerf : Ptr32 Void
                +0xf80 ReservedForOle : Ptr32 Void
                +0xf84 WaitingOnLoaderLock : Uint4B
                +0xf88 Wx86Thread : _Wx86ThreadState
                +0xf94 TlsExpansionSlots : Ptr32 Ptr32 Void
                +0xf98 ImpersonationLocale : Uint4B
                +0xf9c IsImpersonating : Uint4B
                +0xfa0 NlsCache : Ptr32 Void
                +0xfa4 pShimData : Ptr32 Void
                +0xfa8 HeapVirtualAffinity : Uint4B
                +0xfac CurrentTransactionHandle : Ptr32 Void
                +0xfb0 ActiveFrame : Ptr32 _TEB_ACTIVE_FRAME
                +0xfb4 SafeThunkCall : UChar
                +0xfb5 BooleanSpare : [3] UChar

                kd> dt !_PEB
                +0×000 InheritedAddressSpace : UChar
                +0×001 ReadImageFileExecOptions : UChar
                +0×002 BeingDebugged : UChar
                +0×003 SpareBool : UChar
                +0×004 Mutant : Ptr32 Void
                +0×008 ImageBaseAddress : Ptr32 Void
                +0×00c Ldr : Ptr32 _PEB_LDR_DATA
                +0×010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS
                +0×014 SubSystemData : Ptr32 Void
                +0×018 ProcessHeap : Ptr32 Void
                +0×01c FastPebLock : Ptr32 _RTL_CRITICAL_SECTION
                +0×020 FastPebLockRoutine : Ptr32 Void
                +0×024 FastPebUnlockRoutine : Ptr32 Void
                +0×028 EnvironmentUpdateCount : Uint4B
                +0×02c KernelCallbackTable : Ptr32 Void
                +0×030 SystemReserved : [1] Uint4B
                +0×034 AtlThunkSListPtr32 : Uint4B
                +0×038 FreeList : Ptr32 _PEB_FREE_BLOCK
                +0×03c TlsExpansionCounter : Uint4B
                +0×040 TlsBitmap : Ptr32 Void
                +0×044 TlsBitmapBits : [2] Uint4B
                +0×04c ReadOnlySharedMemoryBase : Ptr32 Void
                +0×050 ReadOnlySharedMemoryHeap : Ptr32 Void
                +0×054 ReadOnlyStaticServerData : Ptr32 Ptr32 Void
                +0×058 AnsiCodePageData : Ptr32 Void
                +0×05c OemCodePageData : Ptr32 Void
                +0×060 UnicodeCaseTableData : Ptr32 Void
                +0×064 NumberOfProcessors : Uint4B
                +0×068 NtGlobalFlag : Uint4B
                +0×070 CriticalSectionTimeout : _LARGE_INTEGER
                +0×078 HeapSegmentReserve : Uint4B
                +0×07c HeapSegmentCommit : Uint4B
                +0×080 HeapDeCommitTotalFreeThreshold : Uint4B
                +0×084 HeapDeCommitFreeBlockThreshold : Uint4B
                +0×088 NumberOfHeaps : Uint4B
                +0×08c MaximumNumberOfHeaps : Uint4B
                +0×090 ProcessHeaps : Ptr32 Ptr32 Void
                +0×094 GdiSharedHandleTable : Ptr32 Void
                +0×098 ProcessStarterHelper : Ptr32 Void
                +0×09c GdiDCAttributeList : Uint4B
                +0×0a0 LoaderLock : Ptr32 Void
                +0×0a4 OSMajorVersion : Uint4B
                +0×0a8 OSMinorVersion : Uint4B
                +0×0ac OSBuildNumber : Uint2B
                +0×0ae OSCSDVersion : Uint2B
                +0×0b0 OSPlatformId : Uint4B
                +0×0b4 ImageSubsystem : Uint4B
                +0×0b8 ImageSubsystemMajorVersion : Uint4B
                +0×0bc ImageSubsystemMinorVersion : Uint4B
                +0×0c0 ImageProcessAffinityMask : Uint4B
                +0×0c4 GdiHandleBuffer : [34] Uint4B
                +0×14c PostProcessInitRoutine : Ptr32
                +0×150 TlsExpansionBitmap : Ptr32 Void
                +0×154 TlsExpansionBitmapBits : [32] Uint4B
                +0×1d4 SessionId : Uint4B
                +0×1d8 AppCompatFlags : _ULARGE_INTEGER
                +0×1e0 AppCompatFlagsUser : _ULARGE_INTEGER
                +0×1e8 pShimData : Ptr32 Void
                +0×1ec AppCompatInfo : Ptr32 Void
                +0×1f0 CSDVersion : _UNICODE_STRING
                +0×1f8 ActivationContextData : Ptr32 Void
                +0×1fc ProcessAssemblyStorageMap : Ptr32 Void
                +0×200 SystemDefaultActivationContextData : Ptr32 Void
                +0×204 SystemAssemblyStorageMap : Ptr32 Void
                +0×208 MinimumStackCommit : Uint4B

            PE和編譯器支持:

                PE文件結構的目錄表(directory table)中有一個是IMAGE_DIRECTORY_ENTRY_TLS (9)線程級局部存儲目錄,如果此處非零的話,PE將會有一個tls節,tls節以結構IMAGE_TLS_DIRECTORY(winnt.h)開始
                typedef struct _IMAGE_TLS_DIRECTORY32 {
                DWORD StartAddressOfRawData;
                DWORD EndAddressOfRawData;
                PDWORD AddressOfIndex;
                PIMAGE_TLS_CALLBACK *AddressOfCallBacks;
                DWORD SizeOfZeroFill;
                DWORD Characteristics;
                } IMAGE_TLS_DIRECTORY32;
                其中PIMAGE_TLS_CALLBACK如下:
                typedef VOID
                (NTAPI *PIMAGE_TLS_CALLBACK) (
                PVOID DllHandle,
                DWORD Reason,
                PVOID Reserved
                );
                為了方便使用TLS,編譯器支持用__declspec(thread)來修飾全局或靜態變量,這樣的變量最終存儲在TLS中,對這些變量的訪問與普通變量一樣,編譯器負責處理其中細節分配索引和初始化等。
                IMAGE_TLS_DIRECTORY32 中的StartAddressOfRawData和EndAddressOfRawData指向的區域保存__declspec(thread)變量的初始值,AddressOfIndex指向的區域保存動態分配的Tls索引。AddressOfCallBacks指向一個回調函數,此函數與 DllMain有同樣的形式,它會在線程創建前被調用,多用來完成__declspec(thread)變量的初始化等,也被用于anti- debugger(如blacklight)。
                Visual Studio C++中對此的支持請參考Thread Local Storage - The C++ Way。
                MASM中可以將tls節中的數據放到data節中,然后使用LordPE等工具改變PE中目錄表中的IMAGE_DIRECTORY_ENTRY_TLS為對應的地址和大小即可,具體請見
                TLS-CallBack +IsDebuggerPresent() Debugger Detection。

            參考文獻
            MSDN
            Thread Local Storage: http://www.windowsitlibrary.com/Content/356/11/5.html
            Thread Local Storage - The C++ Way:http://www.codeproject.com/threads/tls.asp
            TLS-CallBack +IsDebuggerPresent() Debugger Detection:
            http://www.openrce.org/reference_library/anti_reversing_view/26/TLS-CallBack%20+IsDebuggerPresent()%20Debugger




            http://hi.baidu.com/ayarei/blog/item/1cfc9d0262c5900a4bfb511f.html

            posted @ 2008-11-04 21:40 tqsheng 閱讀(550) | 評論 (0)編輯 收藏

            NEG+SBB指令組合的用處

            NEG+SBB指令組合的用處

            在逆向遇到NEG+SBB指令的組合,不明白原因,上網一查,找到了.嘿嘿!
            mov     ebx, eax
            neg      ebx
            push    esi
            sbb      bl, bl

            注:Intel處理器的文檔中聲明NEG指令除了對操作數作符號取反外,它還要根據操作數的值設置CF標志位的值。如果執行NEG指令時操作數為0,則CF將被置為0。如果操作數為非零,則CF將被置為1。

            NEG是一個簡單的取反指令,用來對操作數的算術符號取反——有時候也稱它為2的補碼(two’s complement。譯注:1的補碼與NOT指令對應,是邏輯取反指令)。NEG用C描述的偽代碼:

            Result = -(Operand);

            SBB是一條帶借位的減法指令,這就是說SBB將第二個操作數(即右操作數)加上標志位CF,然后將結果用第一個操作數來減。SBB用C描述的偽代碼:

            Operand1 = Operand1 - (Operand2 + CF);

             

            在上面的指令中NEG的作用應該就是注中的,根據操作數來設置CF標志位的值,如果EBX為0,那么CF將被置為0,如果EBX為非零,則CF將被置為1.然后結合SBB,我們可以將以上4條指令理解為,當EBX等于0時,BL將等于0;EBX大于0時,BL將等于-1.

             

            參考:Reversing:逆向工程揭密-附錄A揭密代碼結構(4)

            // 對返回數進行處理,這是編譯器優化的結果,翻譯成C可能是
            // if (eax)
            // return 1 ;
            // else
            // return 0 ;
            // 求反.執行NEG指令時操作數為0,則CF將被置為0。如果操作數為非零,則CF將被置為1
            /*41A72D*/ NEG EAX
            // 高位借位減法,EAX的值取決于前面的neg指令。對同一個操作數執行減運算,
            // 即用EAX寄存器減去EAX,如果不考慮標志位CF的話,這條指令在數學上是沒有任何意義的。
            // 因為將CF加到了第二個操作數上,所以結果只取決于CF。如果“CF == 1”,那么EAX將變成-1
            /*41A72F*/ SBB EAX,EAX
            /*41A731*/ NEG EAX // 如果EAX=0,非0可能是-1了,取反后就返回1

            posted @ 2008-09-19 10:52 tqsheng 閱讀(831) | 評論 (0)編輯 收藏

            IDA stuff (plugins,articles,idc,etc...)

            From:CRACKL@B

            ftp://nezumi.org.ru/ida.full.zip

            http://old.idapalace.net/

            http://www.d-dome.net/idapython

            http://dkbza.org/data/Introduction%20to%20IDAPython.pdf 

            http://www.reconstructer.org/code/ClassAndInterfaceToNames.zip 

            http://www.reconstructer.org/code/MFC42Ord2FuncNames.zip 

            http://www.reconstructer.org/code/VtablesStructuresFromPSDK2003R2.zip 

            http://www.reconstructer.org/code/IDAAPIHelp%20v0.3.zip

            posted @ 2008-01-28 22:28 tqsheng 閱讀(273) | 評論 (1)編輯 收藏

            LIB 概述

            http://msdn2.microsoft.com/zh-cn/library/0xb6w1f8(VS.80).aspx

            posted @ 2008-01-28 19:57 tqsheng 閱讀(112) | 評論 (0)編輯 收藏

            鏈接時如何選擇C Run-Time(CRT) library

            鏈接時如何選擇C Run-Time(CRT) library
             

            在Windows下有六種類型CRTLib(C運行庫):
            Reusable Library                Switch    Library    Macro(s) Defined
            ----------------------------------------------------------------
            Single Threaded                     /ML       LIBC               (none)
            Static MultiThread                  /MT       LIBCMT         _MT
            Dynamic Link (DLL)              /MD       MSVCRT        _MT and _DLL
            Debug Single Threaded           /MLd      LIBCD          _DEBUG
            Debug Static MultiThread        /MTd      LIBCMTD    _DEBUG and _MT
            Debug Dynamic Link (DLL)    /MDd      MSVCRTD    _DEBUG, _MT, and _DLL

            MT和MD都適用于多線程,其區別是:
            MT為靜態鏈接CRT,這樣編譯出來exe是自包含的,所以會相對大一些,但運行時不用再load CRT庫。
            MD為動態鏈接CRT,編譯出來exe會小一些,運行時需要load CRT,性能有一點點損失。

            任何工程都應該使用同樣的CRT Library。即要么都是/ML,要么都是/MTD, 如此類推。

            如果一個程序中混合使用不同類型的CRT,有時可以通過link,這樣會存在不同CRT的copy,并導致以下問題:
                1)在一個lib中new出來內存,在另一個lib中delete,會crash。
                2)不能在多個lib中共享file handle。
                3)一個lib中設置locale(本地化有關),不能在另一個lib中起作用。

            當工程比較大,包含的lib很多,特別當有外部lib(Third party library)存在時,link很容易發生下面這樣的錯誤。
            LIBCMTD.lib(chsize.obj) : error LNK2005: __chsize already defined in MSVCRTD.lib(MSVCRTD.dll)
            這說明,你的工程使用了不同類型的CRT。這個時候首先一定要堅信這個原則:整個工程用同樣的CRT Lib就可以解決問題。然后耐心一一檢查每個lib。
            如果恰恰某個外部lib用MT,另一個用MD,這個時候就比較痛苦。
                如果有他們源碼,就編譯一個MT or MD類型的lib,以統一使用一個類型CRT。
                如果沒有,那可能只好選擇其他的lib。

             原文地址 http://blog.vckbase.com/michael/archive/2005/06/30/9000.html

            posted @ 2008-01-28 19:53 tqsheng 閱讀(519) | 評論 (1)編輯 收藏

            ida plus

            http://www.woodmann.net/yates/documents/35.html

            posted @ 2008-01-25 12:13 tqsheng 閱讀(208) | 評論 (1)編輯 收藏

            http://www.ccso.com/faq.html

            IDA Pro FAQ

            Q How do I generate FLIRT signature from my own libraries ?

            A The process is simple if you have installed the FLAIR tools. As an example, we'll use an file called api.lib. First a pattern file should be created. The command

             

            plb api(.lib) api(.pat)

            creates a pattern file whose format is described in our FLIRT paper. Have a look at this file with a text editor.Then we'll create a signature file with the command

             

            sigmake api(.pat) api(.sig)

            and copy the resulting api.sig file in the IDA Pro SIG subdirectory.

            Q How do I apply my own SIGs to the disassembly ?

            A Open the signature window through the View Menu. Press the INS key. Wait a few seconds until the list of available signatures is build. Move the cursor on the line containing your sig file and press the ENTER key.


            Q How do I prevent IDA from applying SIGs to the disassembly ?

            A Open the IDA.CFG file and modify the ANALYSIS configuration word in order to exclude the AF_FLIRT option.


            Q How do I define high level structures ?

             

            A See this short tutorial

            Q How do I use other processors with IDA Pro ?

             

            A You must specify the processor you wish to use on the command line. For example, if you want to disassemble a 8051 binary, IDA Pro should be started as follows (if you are using the Windows version of IDA Pro).

            IDAW -p8051


            Q How do I use IDC

            A see this example


            Q How do I load debugging information, MAP or SYM files into IDA ?

             

            A The following procedure may be used to load debugging information, MAP and SYM files into a disassembly. This procedure is a temprarory solution, as future versions of IDA will have a built-in support of debugging information.
              Convert debugging information into text using your favorite dumper. (Borland's TDUMP.EXE is a good choice when dealing with Borland and Microsoft debugging information). Load the text into a text editor and convert it into IDC script:
              
                              static main() {
                              MakeName(addr,name);
                              ...........
                              }
                              
              where addr - address should be replaced be the address of the name and name is string constant. Example:
              
                              static main() {
                              MakeName(0x10000,"name1");
                              }
                              
              Launch IDA and execute the script by pressing F2 key. The names from the SYM file will appear in the disassembly.

            Q How do I save a fragment of disassembly ?

            A Select the area of the disassembly that you want to save and press ALT-F10.


            Q How do I view the disassembly in C/VB etc?

            A You must create a file called sissy.ini and add the line "LANG_C=Yes". Jokes aside, this is not something IDA can do. The output is ASM.


            Q How do I change the search direction ?

            A By pressing the TAB key

            posted @ 2008-01-25 09:04 tqsheng 閱讀(369) | 評論 (0)編輯 收藏

            庫函數的快速鑒別和識別技術

            標 題: 庫函數的快速鑒別和識別技術
            翻 譯: 月中人
            時 間: 2006-09-07 15:20
            鏈 接: http://bbs.pediy.com/showthread.php?threadid=31636
            詳細信息:

             

             

            庫函數的快速鑒別和識別技術

            文檔編號:

            S002-0017

            原作者:

            Ilfak Guilfanov [DataRescue.com]

            譯者:

            月中人 [PTG]

            審校:

             

            發布時間:

            2007-01-10

            原文標題:

            Fast Library Identification and Recognition Technology

            關鍵詞:

            庫函數,鑒別,識別,簽名,特征文件

            1. 原文版權聲明:

            (c) Copyright 1997 by Ilfak Guilfanov & DataRescue

            Reproduction strictly forbidden

            2. 譯文字典:

            Identification鑒別,即確定一個函數是什么;

            Recognition識別,即從程序中分離出屬于一個函數的那些代碼;

            misidentification錯誤標識

             

             

             

            目錄

            1. 目標

            2. 難點

            3. 要點

            4. 實現

            5. 結果

             


            1         目標

            對于現代高級語言所寫的程序,分離庫函數所費的時間是反匯編的一個主要障礙。我們會因為沒有從中獲得新的知識而覺得時間被浪費了:它只是我們深入分析程序和反映其意圖的算法之前一個必不可少的步驟。遺憾的是,每次反匯編一個新的程序都不得不重復這一步。

            有時,了解一個庫函數的類別能相當大地減輕對程序的分析工作。這對于丟棄無用信息可能極有幫助。舉例來說,一個處理流數據的C++函數通常與程序的主要算法無關。

            請注意一個有意思的現象,每一高級語言程序都使用很多標準庫函數,有時甚至達到所有被調用函數的95%是標準函數。使用某個眾所周知的編譯器編譯的“Hello, world!”程序中有:

                    庫函數        -    58

                    函數main()    -    1

            當然,這是一個人為的例子,但我們的分析確實顯示,真實程序中的函數平均50%是庫函數。這就是為什么反匯編器的使用者不得不花費他一半以上的時間來分離出那些庫函數。對一個未知程序進行分析類似于解答一個巨大的拼字智力游戲:我們確定的字母越多,就越容易猜測下一個字。反匯編過程中,在一個函數里面注解和有意義名字越多,意味著能夠更快地理解它的意圖。象OWLMFC以及其他一些標準庫的廣泛使用,甚至更增加了在目標程序中標準函數所占的成分。

            使用現代技術(如,AppExpert或類似的向導)用C++編的一個中等尺寸的Win32程序,會從10002500個庫函數中調用任何函數。

            我們試圖創造一個識別標準庫函數的算法來輔助IDA用戶。我們希望它是一個實用而且有用的東西,因此必須接受一些限制:

            n         我們只考慮用C/C++編寫的程序

            n         我們不企圖達成完美的函數識別:從理論上講這是不可能的。而且,對某些函數的識別可能導致不良后果。例如,對下面這個函數的識別將會誤導以致產生許多錯誤標識。

                            push    bp

                            mov     bp, sp

                            xor     ax, ax

                            pop     bp

                            ret

            這毫無意義,因為在現代的C++庫中你會發現有許多不同名字的函數與它每個字節都完全相同。

            n         我們只識別和鑒別位于代碼段的函數,而忽略數據段。

            n         當一個函數已經被成功鑒別的時候,我們給它指定一個名字和一個最終的注解。我們不打算提供關于函數參數或函數行為的信息。

            我們還要求做到以下幾點

            n         我們努力完全地避免假陽性。我們認為假陽性(一個被錯誤地鑒別的函數)比假陰性(一個沒有鑒別出來的函數)更糟。理想的情況應該是根本不產生假陽性。

            n         函數的識別需要你提供最低限度的處理器和存儲器資源。

            n         由于IDA的多價結構 - 它支持好幾十種非常不同的處理器 - 鑒別算法必須是獨立于平臺的,即它必須適用于為任何處理器編譯的程序。

            n         應該鑒別main()函數并適當地加以標注,因為我們對庫的啟動代碼不感興趣。

            2         難點

            存儲器的使用量

            識別和鑒別的主要障礙是函數的純數量及其占用存儲空間的大小。如果我們計算所有編譯器‘廠商’為不同存儲器‘模型’生產的所有庫所有‘版本’,所需儲存空間動輒成百上千億字節之巨。

            如果我們試圖考慮OWLMFCMFC及類似的庫,情況更糟。所需要的儲存量是極大的。目前,個人電腦用戶不可能負擔得起劃撥成百上千兆字節的磁盤空間給一個簡單的反匯編工具程序。因此,我們必須采用某種算法,如此便可以減少識別標準庫函數時所需信息的尺寸。當然,由于必須被識別的函數個數多,我們需要一個有效率的識別算法:簡單的暴力搜索并非一個可選方案。

             

            可變性

            另一個的困難在于程序中的‘變數’字節[_variant_ bytes]。有些字節在載入時被修正(被解決),而另一些字節在鏈接時變成常數,但是大部份變數字節是來自引用的外部名字。在那種情況下,編譯器不知道被調用函數的地址,而且保留這些字節的值為零。這種所謂的“修正信息[fixup information]”通常被寫到輸出文件[output file]的一個表(有時叫做“重定位表”或“重定位信息”)。下例包含有變數字節。

            B8 0000s                             mov     ax, seg _OVRGROUP_

            9A 00000000se                        call    _farmalloc

            26: 3B 1E 0000e                      cmp     bx, word ptr es:__ovrbuffer

             

            鏈接器將會試圖解決外部引用,使用所調用的函數的地址替換那些零,但是有些字節仍保留不變:程序中對動態庫的引用或者包含絕對地址的那些字節。這些引用只能在載入時由系統裝載程序解決。它將會試圖解決所有的外部引用而且用絕對地址替換零。當系統裝載程序不能夠解決某個外部引用時,如同該程序引用一個未知DLL的情況一樣,程序就不運行。

            某些鏈接器設置的優化也會讓事情變復雜,因為那些固定的字節有時會被改變。例如:

                           0000: 9A........        call    far ptr xxx

                         被替換成

                           0000: 90                nop

                           0001: 0E                push    cs

                           0002: E8....            call    near ptr xxx

             

            程序會照常運行,但是鏈接器帶來的替換確實讓我們不可能利用函數模板做逐字節對比。一個程序中變數字節的出現使得不可能利用簡單的檢驗和來識別。如果函數沒有包含變數字節,開頭N字節的CRC[循環冗余校驗碼]就足以鑒別和選擇在一個散列表中的一組函數。使用這種表會大大減少鑒別所需的信息大小:函數的名字、它的長度以及檢驗和就夠了。

            我們已經用例子證明了,識別所有的標準庫函數是不可能的,或者甚至是不值得的。還有一個補充證明就是,某些函數是同一的,它們做的事完全相同,只是以不同的方式調用。例如,函數strcmp()fstrcmp()在大規模存儲器模型中是同一的。


            這里我們遇到一個左右為難的問題:有些函數并非無足輕重,而且將它們標注會對用戶有幫助,所以我們不想從識別過程中丟棄這些函數,然而我們無法區別它們。

            更具體些:考慮這個

                            call    xxx

                            ret

                    或者

                            jmp     xxx

             

            乍一看,這些代碼片斷沒有特別之處。問題是它們在標準庫中出現,有時數量相當多。Borland C++ 1.5OS/2編譯器使用的那些庫包含20個這種類型的調用,出現在read()write()等重要的函數中。

            對這些函數的無格式比較不會有什么收獲。區別那些函數的唯一機會是發現它們調用其他的什么函數。通常,所有的短函數(只由2-3條指令組成)都難以識別,而且錯誤識別的概率非常高。然而不識別它們是不好的,因為它會導致級聯的識別失敗:如果我們不識別函數tolower(),我們可能就無法識別引用tolower()strlwr()

             

            版權

            最后,有一個明顯的版權問題:就是一個反匯編器的分發可能不帶那些標準庫。

             


            3         要點

            為了解決以上提出的問題,我們創建一個數據庫,含有我們想要識別的所有庫的所有函數。于是對于反匯編出來的程序每個字節,IDA Pro都檢查它能否標志著某個標準庫函數的開始。

            識別算法所需要的信息保存在一個特征[signature]文件中。每個函數表現為一個模式。模式是一個函數開頭的32個字節,其中所有變數字節用符號標記。例如:

            558BEC0EFF7604..........59595DC3558BEC0EFF7604..........59595DC3 _registerbgidriver

            558BEC1E078A66048A460E8B5E108B4E0AD1E9D1E980E1C0024E0C8A6E0A8A76 _biosdisk

            558BEC1EB41AC55604CD211F5DC3.................................... _setdta

            558BEC1EB42FCD210653B41A8B5606CD21B44E8B4E088B5604CD219C5993B41A _findfirst

             

            其中變數字節顯示為“..”,有些函數開始幾字節組成的序列相同。因此樹結構好象很適合用來儲存它們:

            558BEC

                  0EFF7604..........59595DC3558BEC0EFF7604..........59595DC3 _registerbgidriver

                  1E

                    078A66048A460E8B5E108B4E0AD1E9D1E980E1C0024E0C8A6E0A8A76 _biosdisk

                  B4

                    1AC55604CD211F5DC3                                       _setdta

                    2FCD210653B41A8B5606CD21B44E8B4E088B5604CD219C5993B41A   _findfirst

             

            字節序列保存在樹的結點中。在這個例子中,樹的根包含序列“558BEC”,三個子樹起源于根,分別地以

            字節0E1EB4開始。以B4開始的子樹生出兩個子樹。每個子樹以葉子結束。關于函數的信息保存在那里(上述例子中只有名字是可見的)。

            [注意此處有誤:根據之前列出的4個模式來看,直接源于根的只有0E1E兩個子樹,B4應在1E之后]

            樹數據結構同時達成兩個目標:

            n         存儲器需求減少了,因為我們在樹結點儲存幾個函數共用字節。當然,節省量與具有相同開頭字節的函數數目成比例。

            n         它很適合于加快模式速配。將程序中某個特定位置與一個特征文件中所有函數進行匹配所需的比較次數是以函數數目的對數增長。

            單獨以函數開頭的32個字節為基礎下結論不是很明智。正如前面所提到的,現代的真實庫包含一些以相同字節開始的函數:

            558BEC

                  56

                    1E

                      B8....8ED8

                               33C050FF7608FF7606..........83C406

                                                                  8BF083FEFF

                                0. _chmod   (20 5F33)

                                1. _access (18 9A62)

             

            當兩個函數有相同的開頭32個字節時,它們被儲存在樹的同一個葉子中。為了解決這種情況,我們從位置33起開始計算那些字節的CRC16直到遇到第一個變數字節為止。CRC被儲存在特征文件中。用于計算該CRC的字節數目也需要保存,因為這個數目因不同函數而不同。在上述例子中,計算_chmod函數(字節3352)的CRC16用了20字節,而_access函數用18字節。

            當然,有一種可能性是,第一個變數字節處在33d[十進制數]位置。則用來計算CRC16的字節序列的長度等于零。但實際上,這很少地發生,而且這個算法所引起錯誤識別的次數非常低。

            有時函數有相同的起始32字節模式,而且有相同的CRC16,如下面的例子中

            05B8FFFFEB278A4606B4008BD8B8....8EC0

                      0. _tolower (03 41CB) (000C:00)

                      1. _toupper (03 41CB) (000C:FF)

             

            真抱歉:只有3個字節用來計算CRC16,而且兩個函數的CRC16是相同的。在這種情況下,我們將會嘗試尋找到某個位置,使得同一葉子的所有函數在那里有不同的字節。(在我們的例子中這個位置是32+3+000C[注意數的進制]

            但是既使這個方法也不能識別所有的函數。看另外一個例子:

            ... (這里只顯示樹的一部分)

                            0D8A049850E8....83C402880446803C0075EE8BC7:

                              0. _strupr (04 D19F) (REF 0011: _toupper)

                              1. _strlwr (04 D19F) (REF 0011: _tolower)

             

            這些函數在非變數字節處完全相同,而只有它們調用的函數不同。在這個例子中區別兩函數的唯一方法是檢驗偏移11處的那條指令所引用的名字。

            最后這個方法有一缺點:函數_strupr()_ strlwr()的正確識別依賴于函數_toupper()_tolower()的識別。這意味著在因為缺少對_toupper()_tolower()的引用而識別失敗的情況下,我們必須推遲識別并且稍后在找到_tolower()_toupper()后重做識別。這影響了算法的整體設計:我們需要做第二趟以解決那些被推遲的識別。幸運地,后一趟只應用在程序中少數地方。

            最后,你會發現有的函數在非變數字節處完全相同,[而且變數字節]引用相同的名字,但是這些函數被以不同的名字調用。那些函數有相同的實現但有不同的名字。令人驚訝的是,在標準庫中,尤其在C++庫中,這是常見的情形。

            我們稱這種情形為‘沖突’,即隸屬于同一葉子的一些函數無法通過上述方法相互區別。下面是一個典型的例子:

            558BEC1EB441C55606CD211F720433C0EB0450E8....5DCB................

               0. _remove (00 0000)

               1. _unlink (00 0000)

            或者

            8BDC36834702FAE9....8BDC36834702F6E9............................

               0. @iostream@$vsn            (00 0000)

               1. @iostream_withassign@$vsn (00 0000)

             

            人工智能是解決這些沖突的唯一辦法。因為當前目標是效率和速度,所以我們決定把人工智能作為該算法的未來發展方向。


            4         實現

            IDA Pro 3.6版中,該算法的實際實現幾乎完全符合以上描述。我們已限制算法只使用于CC++語言編寫的程序反匯編,但是未來絕對有可能為其他庫編寫預處理器[pre-processors]

            為每個編譯器提供一個單獨的特征文件。這樣隔離降低了跨編譯器的鑒別沖突概率。一個特別的特征文件,名為啟動特征文件[startup signature file],被應用于所反匯編程序的入口以確定生成它所用的編譯器。一旦得以鑒別,我們就知道應該使用哪個特征文件來反匯編其它部分。我們的算法成功地辨別市場上大多數常用的編譯器的啟動模塊。

            既然我們以一個特征文件儲存適合于一個編譯器的所有函數簽名,所以就不必要區別這些編譯器的版本和/或庫的存儲器模型(小的、緊湊的、中等的、大的、極大的)。

            對于反匯編文件的每個格式,我們使用專門的啟動特征文件。特征文件exe.sig用于MS DOS下運行的程序,而lx.signe.sig用于OS/2下的,等等。

            為了降低短函數的錯誤識別概率,我們必須完全地記錄任何一個對外部名字的引用--假如存在這樣的引用。這也許會在某種程度上降低函數識別成功的機會,但是我們認為事實證明采用這樣的方式是正確的。錯誤地識別不如不識別。我們創建特征文件時不使用某些短函數(少于4字節),它們不包含對外部名字的引用,而且我們也不企圖去識別這類函數。

            來自<ctype.h>的函數很短,但它們引用符號類型數組,所以我們決定把對這個數組的引用作為一個例外:我們計算符號類型數組的CRC16,并將它儲存特征文件中。

            沒有人工智能,我們用自然智能解決沖突。特征文件的創作人決定特征文件中函數的取舍。選擇函數是很容易的,而且實際上是編輯一個文本文件。

            函數的模式不是以它們的最初形式儲存在一個特征文件中(即,它們看起來不像例子那樣)。我們不使用那些形式的模式,而是儲存一些比特數組,這些位用來確定某些字節的改變,即字節的數值被分離儲存。因此,除了函數的名字以外,特征文件沒有包含來自原始庫文件的字節。特征文件的創建包括兩個階段:庫的預處理和特征文件的創建。在第一個階段使用‘parselib’這個程序。它預處理*.obj*.lib文件以產生一個模式文件。模式文件包含函數的模式、它們的名字、它們的CRC16以及創建特征文件所需的所有其他信息。在第二個階段,‘sigmake’這個程序從模式文件建立特征文件。

            分為兩個階段允許sigmake工具程序與輸入文件的格式無關。因此未來將有可能為非*.obj*.lib格式的文件編寫另外的預處理器。

            我們決定壓縮(使用InfoZip算法)所創建的特征文件以減少儲存它們所需的磁盤空間。

            為了方便用戶,我們試圖盡最大可能識別main()函數。鑒別這個函數的算法因編譯器不同而不同、因程序不同而不同。(DOS/OS2/Windows/GUI/Console...)。

            該算法作為一個文本字符串被寫入一個特征文件中。遺憾的是,我們還不能自動產生該算法。

             


            5         結果

            事實證明那些特征文件壓縮得很好;它們的壓縮系數可能大于2。這個壓縮率的理由是,一個特征文件大約95%是函數名字。(例子:用于MFC 2.x的特征文件在壓縮前是2.5MB,壓縮是700Kb。它包含33634個函數名字;平均每個函數用21字節儲存。通常,一個庫文件尺寸對一個特征文件尺寸的比率從100500不等。

            正確識別函數的百分比非常高。我們的算法識別出那個“Hello World”程序中除一個函數之外的所有函數。未被識別的函數只有一條指令:

                    jmp     off_1234

             

            尤其讓我們滿意的是沒有錯誤識別。然而這并不意味著錯誤永遠不會發生。請注意,該算法只對函數工作。

            數據有時位于代碼段,而且因此我們需要把某些名字標記為“數據名”,而非“函數名”。在一個現代的大型庫文件中檢驗所有名字并標記所有的數據名字是不容易的。

            我們計劃在未來某時實現這些數據名字的標記。


            ©2000-2007 PEdiy.com All rights reserved.
            By PEDIY

            posted @ 2008-01-24 12:05 tqsheng 閱讀(583) | 評論 (0)編輯 收藏

            翻譯:向PE中注入代碼

                 摘要: 標 題: 翻譯:向PE中注入代碼翻 譯: arhat時 間: 2006-04-16 00:53 鏈 接: http://bbs.pediy.com/showthread.php?threadid=24183 詳細信息: Inject your code to a Portable Executable file向PE中注...  閱讀全文

            posted @ 2008-01-24 12:02 tqsheng 閱讀(4386) | 評論 (1)編輯 收藏

            從IDA中提取代碼做匯編注冊機之C/C++篇

            標 題: 從IDA中提取代碼做匯編注冊機之C/C++篇
            作 者: laomms
            時 間: 2006-12-22 23:22
            鏈 接: http://bbs.pediy.com/showthread.php?threadid=36799
            詳細信息:

                繼上篇那個VB后,我也想做個C/C++類的例子,正好看到FreeSoul寫的FScrackme2,所以寫了這篇文章。
                FScrackme2應該是在lunix下取了GNU中的 GCC.exe 和 G++.exe來編譯的一個C程序! 所以用PEID來看語言類型是MingWin32 GCC 3.x。也就是GCC編譯的C程序。

            先來分析程序,找到真正的注冊碼并不難,OD中的算法部分:
            00401AE7  |.  8945 9C       MOV [LOCAL.25],EAX                       ; |
            00401AEA  |.  837D A0 03    CMP [LOCAL.24],3                         ; |用戶名長度必須大于3位
            00401AEE  |.  0F8E C2000000 JLE <FScrackm.loc_401BB6>                ; |
            00401AF4  |.  837D 9C 1A    CMP [LOCAL.25],1A                        ; |注冊碼長度必須大于27位
            00401AF8  |.  0F8E B8000000 JLE <FScrackm.loc_401BB6>                ; |
            ...
            00401B62  |.  8B45 9C       MOV EAX,[LOCAL.25]
            00401B65  |.  894424 0C     MOV DWORD PTR SS:[ESP+C],EAX             ;  注冊碼長度
            00401B69  |.  8B45 A0       MOV EAX,[LOCAL.24]
            00401B6C  |.  894424 08     MOV DWORD PTR SS:[ESP+8],EAX             ;  用戶名長度
            00401B70  |.  8B45 A4       MOV EAX,[LOCAL.23]
            00401B73  |.  894424 04     MOV DWORD PTR SS:[ESP+4],EAX             ;  注冊碼ASCII
            00401B77  |.  8B45 EC       MOV EAX,[LOCAL.5]
            00401B7A  |.  890424        MOV DWORD PTR SS:[ESP],EAX               ;  用戶名ASCII
            00401B7D  |.  E8 1C010000   CALL <FScrackm.sub_401C9E>               ;  主要算法
            00401B82  |.  85C0          TEST EAX,EAX
            00401B84  |.  75 18         JNZ SHORT <FScrackm.loc_401B9E>          ;  判斷返回值是否為0


            ================================================================================================
            CALL <FScrackm.sub_401C9E>  主要算法:

            00401D33 > > \8B45 0C       MOV EAX,DWORD PTR SS:[EBP+C]            
            00401D36   .  8038 4E       CMP BYTE PTR DS:[EAX],4E                 ;  對比第一位注冊碼是否為“N”
            00401D39   .  74 0F         JE SHORT <FScrackm.loc_401D4A>
            00401D3B   .  C785 4CFFFFFF>MOV DWORD PTR SS:[EBP-B4],1
            00401D45   .  E9 7E070000   JMP <FScrackm.loc_4024C8>
            00401D4A > >  8B45 0C       MOV EAX,DWORD PTR SS:[EBP+C]            
            00401D4D   .  40            INC EAX
            00401D4E   .  8038 61       CMP BYTE PTR DS:[EAX],61                 ;  對比第二位注冊碼是否為“a”
            00401D51   .  74 07         JE SHORT <FScrackm.loc_401D5A>
            00401D53   .  C745 94 00000>MOV DWORD PTR SS:[EBP-6C],0
            00401D5A > >  8B45 0C       MOV EAX,DWORD PTR SS:[EBP+C]            
            00401D5D   .  83C0 02       ADD EAX,2
            00401D60   .  8038 52       CMP BYTE PTR DS:[EAX],52                 ;  對比第三位注冊碼是否為“R”
            00401D63   .  74 0F         JE SHORT <FScrackm.loc_401D74>
            00401D65   .  C785 4CFFFFFF>MOV DWORD PTR SS:[EBP-B4],1
            00401D6F   .  E9 54070000   JMP <FScrackm.loc_4024C8>
            00401D74 > >  8B45 0C       MOV EAX,DWORD PTR SS:[EBP+C]           
            00401D77   .  83C0 03       ADD EAX,3
            00401D7A   .  8038 46       CMP BYTE PTR DS:[EAX],46                 ;  對比第四位注冊碼是否為“F”
            00401D7D   .  74 0F         JE SHORT <FScrackm.loc_401D8E>
            00401D7F   .  C785 4CFFFFFF>MOV DWORD PTR SS:[EBP-B4],1
            00401D89   .  E9 3A070000   JMP <FScrackm.loc_4024C8>
            ...
            00401E8B   .  83C0 04       ADD EAX,4
            00401E8E   .  0FB600        MOVZX EAX,BYTE PTR DS:[EAX]
            00401E91   .  3A45 87       CMP AL,BYTE PTR SS:[EBP-79]              ;  對比第5位開始5位注冊碼
            00401E94   .  74 0F         JE SHORT <FScrackm.loc_401EA5>

            ...

            00401EEA   .  83C1 09       ADD ECX,9
            00401EF6   .  0FB601        MOVZX EAX,BYTE PTR DS:[ECX]
            00401EF9   .  3A02          CMP AL,BYTE PTR DS:[EDX]                 ;  對比第10位注冊碼
            00401EFB   .  74 0F         JE SHORT <FScrackm.loc_401F0C>
            ...
            00401F4A   .  83C2 0A       ADD EDX,0A
            00401F4D   .  8B85 70FFFFFF MOV EAX,DWORD PTR SS:[EBP-90]            ;  對比第11位注冊碼...
            00401F8B   .  E8 30420000   CALL <FScrackm.isalpha>                  ; 第12位后6位注冊碼,必須為字母
            ..
            00401FB5   .  E8 F6410000   CALL <FScrackm.isupper>                  ; 第12位后6位注冊碼,必須大寫
            ...
            0040205F   .  83C0 0A       ADD EAX,0A                               ;  第10位后
            00402075   .  0FBEC0        MOVSX EAX,AL
            00402078   .  39C1          CMP ECX,EAX                              ;  對比第11位開始3位的注冊碼
            0040207A   .  74 0F         JE SHORT <FScrackm.loc_40208B>
            ...
            004020B1   .  0FBEC0        MOVSX EAX,AL
            004020B4   .  39C1          CMP ECX,EAX                              ;  對比第17位開始倒數3位的注冊碼
            004020B6   .  74 44         JE SHORT <FScrackm.loc_4020FC>
            ...
            00402125   .  83C0 11       ADD EAX,11                               ; 第17位后
            00402128   .  0FBE00        MOVSX EAX,BYTE PTR DS:[EAX]              
            0040212B   .  890424        MOV DWORD PTR SS:[ESP],EAX               
            0040212E   .  E8 6D400000   CALL <FScrackm.isdigit>                  ; \第18位開始的6位必須為數字
            00402133   .  85C0          TEST EAX,EAX
            00402135   .  75 0F         JNZ SHORT <FScrackm.loc_402146>
            ...
            0040220D   .  0FB601        MOVZX EAX,BYTE PTR DS:[ECX]
            00402210   .  3A02          CMP AL,BYTE PTR DS:[EDX]                 ;  對比第18位后的6位注冊碼
            00402212   .  74 0F         JE SHORT <FScrackm.loc_402223>
            ...
            00402230   .  83C0 17       ADD EAX,17
            00402233   .  8038 2D       CMP BYTE PTR DS:[EAX],2D                 ;  對比第24位注冊碼,必須為“-”號
            00402236   .  74 07         JE SHORT <FScrackm.loc_40223F>
            ...
            004022C7   .  83C1 18       ADD ECX,18
            004022CA   .  8B85 58FFFFFF MOV EAX,DWORD PTR SS:[EBP-A8]
            004022D0   .  0FBE10        MOVSX EDX,BYTE PTR DS:[EAX]
            004022D3   .  0FB601        MOVZX EAX,BYTE PTR DS:[ECX]
            004022D6   .  3A842A 78FFFF>CMP AL,BYTE PTR DS:[EDX+EBP-88]          ;  對比第25位注冊碼
            004022DD   .  74 0F         JE SHORT <FScrackm.loc_4022EE>
            ...
            00402474   .  83C2 19       ADD EDX,19
            00402477   .  8B85 50FFFFFF MOV EAX,DWORD PTR SS:[EBP-B0]
            0040247D   .  3802          CMP BYTE PTR DS:[EDX],AL                 ;  對比第26位注冊碼
            0040247F   .  74 07         JE SHORT <FScrackm.loc_402488>
            00402481   .  C745 94 00000>MOV DWORD PTR SS:[EBP-6C],0
            00402488 > >  8B45 0C       MOV EAX,DWORD PTR SS:[EBP+C]             
            0040248B   .  83C0 1A       ADD EAX,1A
            0040248E   .  8038 44       CMP BYTE PTR DS:[EAX],44                 ;  對比第27位注冊碼是否為“D”
            00402491   .  74 07         JE SHORT <FScrackm.loc_40249A>
            ...
            0040249A > > \837D 14 1B    CMP DWORD PTR SS:[EBP+14],1B             ;  對比注冊碼長度是否為27位
            0040249E   .  74 0C         JE SHORT <FScrackm.loc_4024AC>

            ==================================================================================================


                我們主要是討論寫注冊機,所以算法具體不去討論。我們現在所知道的是,用戶名要大于三位,注冊碼必須為27位,而且我們知道了每個注冊碼比較的地方。CALL 00401C9E里面是具體的算法,里面還有很多子函數,想提取這樣一個含有很多子程序的代碼到注冊機里在OD中好象沒有好的方法,只有手動提,而在IDA中就有辦法,這得益于最早由dreaman寫的提取函數的腳本,我稱它為GetCall.IDC(http://bbs.pediy.com/showthread.php?s=&threadid=23231),在IDA中,只要將光標定位于一個函數的起始代碼,運行腳本后,它會截取所有該函數的代碼,包括里面所有的子函數代碼,并在文件目錄保存匯編代碼為一個ASM文件。真是太方便了。讓我們行動。
            IDA反匯編FScrackme2,“G”到401C9E,菜單“文件”-“IDC文件”,運行腳本。FScrackme2目錄中已經生成了FScrackme2Part.asm。但是在這之前,對于這個軟件,需要在IDA中動動手腳。因為軟件是GCC寫的,IDA的腳本gcc32rtf.sig自動把GCC的庫函數識別出來了:
            .text:00401DCF                 call    __Znaj

                這本來是個好事,我也想找GCC的運行庫,然后將它轉換成MASM的庫文件,這樣,這些CALL就可以直接在MASM中引用了,寫注冊機就非常方便了。但是找不到這樣的運行庫。而GetCall.IDC腳本只要碰到被IDA識別出來的函數,它就不進去拷里面的子函數,所以,解決方法只有一個,將IDA中的SIG文件夾下的gcc32rtf.sig文件刪除,再讓IDA反匯編FScrackme2,再拷CALL 401C9E里的代碼。這樣拷出來的的子函數就比較全了。(當然我也把所有的GCC的庫函數提取出來做個備份,誰需要的話跟我聯系。)
            現在就已經把代碼全部拷出到FScrackme2Part.asm了,我們不管三七二十一先把這段匯編代碼拷到一個匯編注冊機模板里再說,就是上次那個模板,當然這樣在RADASM中運行,錯誤會非常多,有錯就改嘛,中國人的好作風。
            因為是C語言類的,所以不可避免的用到C運行庫msvcrt.dll。所以看到匯編代碼中很多對msvcrt的調用,比如:
            .text:00401F8B                 call    isalpha
            .text:00401D14                 call    isalnum

                先解決這個問題。有了上篇的文章,這已經不是問題了,用Dll2inc將msvcrt.dll轉換為MASM的msvcrt.lib和msvcrt.inc文件,然后在匯編代碼中調用這兩個文件。這樣就可以直接在匯編中調用msvcrt的庫函數了。
            然后繼續讓RADASM找出錯誤,一步一步來解決,一般的方法是將RADASM中的錯誤提示地址復制出來,在IDA中G到該地址,看數據是屬于哪個段的,如果是.text可執行代碼段的子函數,就用GetCall腳本復制出來粘貼到匯編代碼區,如果是.bss、.rdata、.data 等數據段,就拷貝到匯編代碼的.DATA區,LINUX中還會出現.stab .stabstr .comment .note .shstrtab .symtab .strtab,不過這些都沒用。我想在下篇結束篇專門寫如何從IDA中拷代碼,結合具體實例講的詳細些。在這里,拷好的代碼就看附件中的注冊機代碼。
            拷好并修改好后這儼然是用匯編代碼仿制FScrackme2,但是文件大小比原來小了N倍,執行速度也快了不少。
            做成個仿制FScrackme2還不行,我們是要做它的注冊機。
            很多crackme都可以通過用戶名算出個結果,然后將注冊碼也通過運算得到這個結果,那就可以通過注冊碼算法的逆運算推出真實的注冊碼。
            但是這個crackme是個正向的,它就是通過運算得到一個個注冊碼,然后將輸入的注冊碼也一一對比。

            +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            對于這種crackme寫注冊機時我提供一種解決思路,就是制造一個“偽注冊碼”,然后將程序里算出的一個個真實的注冊碼重新存到一個地方,這個地方的字符串就是真的注冊碼了。
            +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

                首先說偽注冊碼,只要符合條件的任何字符都行。我這里為了減少彎路,根據軟件的要求:第12到17位必須為大寫字母,第18位和第24位必須為數字,我提供個名稱為TEMP的偽注冊碼:12345678901ABCDEF123456789D:
            .data
            Temp            db '12345678901ABCDEF123456789D',0

            我將一個個真實的注冊碼存到SerialBuffer中:
            invoke SetDlgItemText,hDlg,IDC_SERIAL,addr SerialBuffer

            其次要將所有對比注冊碼的地方都改為移動真實的注冊碼到SerialBuffer,并且將那些對比發生錯誤跳轉到退出的地方都“爆掉”,相當于先爆破再復制代碼:
            cmp  byte ptr [eax],  4Eh                  ;對比第一位注冊碼是否為“N”
            mov      [SerialBuffer+0],4Eh                 ;將注冊碼第一位“N”寫回
            jmp  short loc_401D4A                     ;避免退出,原來是je  401D4A    

            再次要注意原來程序中循環取輸入的注冊碼進行對比的地方,我們要將它改為循環存儲到SerialBuffer中,這就需要個累計參數,可以利用原程序中循環的時候對比是否循環完的那個參數,用那個非常爽:
            mov  [ebp+var_8C], 1

            cmp  [ebp+var_8C], 6                                                ;是否取完
            ….
            mov  al,  [edx]                              ;對比第18位后的6位注冊碼
            xor      ecxecx
            mov      cl,  byte ptr [ebp+var_8C]          ;循環中的對比參數
            mov      [SerialBuffer+ecx+10h],al               ;寫回第18位后的6位注冊碼
            jmp  short loc_402223                ;避免退出
            mov  [ebp+var_B4], 1
            jmp  loc_4024C8                      ;跳到退出

            lea  eax, [ebp+var_8C]
            inc  dword ptr [eax]                 ;累計

            最后還有一點,就是用前面已經計算出來的正確注冊碼來推算后面部分的注冊碼,這時,不能偽注冊碼來推算了,因為它本身是錯誤的,所以推算出來的后面部分也是錯的,要替換成真實的注冊碼,如:
            mov  eax, [ebp+arg_4]  ;注意這里,這里是將已算出的注冊碼第23位拿來運算,所以要改成:
            mov eaxoffset SerialBuffer  ;將已經算出的注冊碼放到EAX,當然也包括已算出的第23位
            mov  [esp+0C8h+var_C8], eax
            call  sub_4024FE

            然后我們來看看原來程序取用戶名和注冊碼的過程,我們可以替換成取用戶名和偽注冊碼:
            00401B65  |.  894424 0C     MOV DWORD PTR SS:[ESP+C],EAX             ;  注冊碼長度
            00401B69  |.  8B45 A0       MOV EAX,[LOCAL.24]
            00401B6C  |.  894424 08     MOV DWORD PTR SS:[ESP+8],EAX             ;  用戶名長度
            00401B70  |.  8B45 A4       MOV EAX,[LOCAL.23]
            00401B73  |.  894424 04     MOV DWORD PTR SS:[ESP+4],EAX             ;  注冊碼ASCII
            00401B77  |.  8B45 EC       MOV EAX,[LOCAL.5]
            00401B7A  |.  890424        MOV DWORD PTR SS:[ESP],EAX               ;  用戶名ASCII
            00401B7D  |.  E8 1C010000   CALL <FScrackm.sub_401C9E>               ;  主要算法
            00401B82  |.  85C0          TEST EAX,EAX
            00401B84  |.  75 18         JNZ SHORT <FScrackm.loc_401B9E>          ;  判斷返回值是否為0

            只要改為:
            invoke lstrlenaddr Temp                          ;取偽注冊碼長度
            mov  [esp+98h+var_8C], eax      
            invoke lstrlenaddr NameBuffer                    ;取用戶名長度
            mov  [esp+98h+var_90], eax             
            mov  [esp+98h+var_94], offset Temp              ;裝入偽注冊碼
            mov  [esp+98h+var_98], offset NameBuffer        ;裝入用戶名
            call  sub_401C9E                                 ;調用算法CALL
            test  eaxeax
            jnz  loc_401B9E

                我們還可以利用原來注冊碼錯誤的對話框的地方來提示對用戶名各種限制,比如要求第一位和最后一位必須是字母等。
                這樣弄好后,到最后一位注冊碼算好,所有的真實注冊碼也就已經全部存到SerialBuffer中了。
                如果還有錯誤,最好的辦法就是在RADASM中用OD調試跟蹤錯誤。
                注冊機的源代碼我已經放在附件里,最好結合原程序看看。注冊機里我已經做了比較詳細的注釋了。
                注冊機中的全部代碼都拷自FScrackme2在IDA中反匯編后的代碼,也就是幾乎全部是算法函數CALL 401C9E里的代碼。我盡量保持“原汁原味”,雖然有些代碼完全可以刪除,但是直接拷貝比判斷該刪除哪些要好。
                主要就是加入了存儲真實注冊碼的過程,看看每個注冊碼的存儲方法,慢慢體會。

            附件:單擊下載

            【版權聲明】: 本文原創于看雪技術論壇, 轉載請注明作者并保持文章的完整, 謝謝!

                                                                   2006年12月24日
                                                                                                                                   


            ©2000-2007 PEdiy.com All rights reserved.
            By PEDIY

            posted @ 2008-01-24 12:00 tqsheng 閱讀(1979) | 評論 (0)編輯 收藏

            黑客反匯編揭密(中文版).pdf

            http://www.shubulo.com/thread-34984-1-1.html

            posted @ 2007-12-18 08:46 tqsheng 閱讀(1802) | 評論 (6)編輯 收藏

            真假盒裝的鑒別

            我最近買了2個酷睿~才發現的現在壽光的賣電腦 href=http://detail.zol.com.cn/desktop_pc_index/subcate27_list_1.html style=text-decoration:underline target=_blank>電腦的奸商實在是太多了~我沒數碼相機否則就給大家把照片發上來!現在詳細的說一下~希望給大家有所幫助!真盒:封口的標簽字跡非常清晰~并且背景是帶有金屬光澤的就是類似磨沙的會反光的銀色!假盒背景只是簡單的銀色沒有金屬顆粒感!認證標簽左邊都有防偽全息圖~為一個穿戴類似阿拉伯帶風鏡的人站著用雙手去觸摸一個球體并且INTEL的標志是橫排列的還有這個標簽的背景是類似線路板樣步線一樣的的線條假的卻沒有~~假的卻非常模糊基本看不出人~~INTEL的標志中的E是下沉的~真盒是這樣寫的core~tm ~2 Duo Processor E4400.LEGA775 Pkg 假盒沒有TM標志~并且字跡也是異常模糊~真盒2.0 GHZ.2MB Cache.800MHZ FSB 假盒直接沒有這些字~總之假盒字跡非常模糊~但是一般沒有對比難發現!!我自認為精通了都買第2塊時才發現其中的奧秘~還有真盒的風扇上的標簽INTEL后有R的標志假的就沒有~并且真盒風扇比假盒沉一點點~!!真的條形碼顏色深~假的顏色非常淺!!真盒標簽右上角的鑰匙圖形淺藍色的有金屬感并且有點反光有凹凸感~而假的就是深藍色~不發光也沒有凹凸感!!!!還有風扇的托架金屬是那種帶有黑色感覺的~假的就是只發亮的!買CPU是還要看步進~~就是所謂的MO和DO!MO的是好的DO是的老的!!還有外包裝盒上所有酷睿的標志都是特殊印刷的非常亮~并且顏色鮮明~都凸出盒面一點!這里所說適用于現在所有的酷睿系列CPU!請大家以后多加注意~因為原裝后封和原裝原封的價格是差100多元的~而且風扇也沒原裝原封的好!請大家互相轉告!!!別讓這個帖子沉下去!我現在所知道的就是這些了~大家有更詳細的可以繼續添加!!zol

            posted @ 2007-12-13 12:45 tqsheng 閱讀(145) | 評論 (0)編輯 收藏

            僅列出標題
            共25頁: First 17 18 19 20 21 22 23 24 25 
            国产精品无码久久久久久| 精品久久久久久国产三级| 久久精品国产半推半就| 99久久国产宗和精品1上映| 色8激情欧美成人久久综合电| 天天久久狠狠色综合| 国产69精品久久久久777| 国产精品美女久久久久| 狠狠色丁香婷综合久久| 51久久夜色精品国产| 一级做a爰片久久毛片人呢| 国产精品内射久久久久欢欢| 亚洲国产精品人久久| 狠狠久久综合伊人不卡| 久久久久亚洲AV成人网人人网站| 国产精自产拍久久久久久蜜| 久久久精品人妻无码专区不卡| 久久久久人妻一区精品果冻| 一本久久综合亚洲鲁鲁五月天亚洲欧美一区二区| 久久久久久青草大香综合精品| 久久亚洲欧洲国产综合| 国产精品一区二区久久精品涩爱 | 国产免费久久精品丫丫| 久久强奷乱码老熟女网站| 久久精品综合网| 久久91精品国产91久久麻豆| 亚洲欧美日韩精品久久| 一级a性色生活片久久无| 无码AV中文字幕久久专区| 国产精品美女久久久m| 久久精品草草草| 无码任你躁久久久久久久| 久久亚洲精品成人AV| 久久97久久97精品免视看秋霞| 久久天天躁狠狠躁夜夜躁2014| 粉嫩小泬无遮挡久久久久久| 精品久久人人爽天天玩人人妻| 亚洲精品乱码久久久久久蜜桃不卡 | 99久久精品毛片免费播放| 久久久亚洲精品蜜桃臀| 久久精品国产亚洲av麻豆色欲|