all these options — automatable
4. MS-DOS INFECTIONS
SOFTWARE REPORTING LOCATION DATE VIRAL INFECTION
a. Unlock Masterkey Kennedy Space Center Oct 89 Vienna
b. SARGON III Iceland Sep 89 Cascade (1704)
c. ASYST RTDEMO02.EXE Fort Belvoir Aug 89 Jerusalem-B
d. Desktop Fractal Various Jan 90 Jerusalem (1813)
Design System
e. Bureau of the Government Printing Jan 90 Jerusalem-B
Census, Elec. County Office/US Census Bureau
& City Data Bk., 1988
f. Northern Computers Iceland Mar 90 Disk Killer
(PC Manufacturer shipped infected systems.)
5. MACINTOSH INFECTIONS
SOFTWARE REPORTING LOCATION DATE VIRAL INFECTION
a. NoteWriter Colgate College Sep 89 Scores and nVIR
.......
https://groups.google.com/forum/#!original/comp.virus/XJCfYR9T6nI/azflHz5goooJ
lots of (but not all) early virus software was ‘‘for fun’’
not trying to monetize malware
hard: Internet connections uncommon
0x01000x01000x0100:
mov $0x4f28, %cx
/* b9 28 4f */
0x0103:
mov $0x9e4e, %si
/* be 4e 9e */
mov %si, %di
push %ds
/* more normal
program
code */
....
0x0700: /* end */
\(\Rightarrow\)
0x0100: jmp 0x0700
0x0103: mov $0x9e4e, %si
...
0x0700:
push %cx
... // %si <- 0x903
mov $0x100, %di
mov $3, %cx
rep movsb
...
mov $0x0100, %di
push %di
xor %di, %di
ret
...
0x0903:
.bytes 0xb9 0x28 0x4f
...
// start of virus code
0x0700:
push %cx ; initial value of %cx matters??
mov $0x8fd, %si // %si <- beginning of data
// address 0x8fd computed during infection
mov %si, %dx ; save %si
; movsb uses %si, so
; can't use another register
add $0xa, %si // offset of saved code in data
mov $0x100, %di ; target address
mov $3, %cx // bytes changed
; copy %cx bytes from (%si) to (%di)
; = 3 bytes from 0x903 to 0x100
rep movsb
...
...
// start of virus data
0x8fd:
...
// saved copy of original application start code
0x903: .byte 0xb9 .byte 0x28 .byte 0x4f
0x08e7:
pop %cx ; restore initial value of %cx, %sp
xor %ax, %ax ; %ax <- 0
xor %bx, %bx ; %bx <- 0
xor %dx, %dx ; %cx <- 0
xor %si, %si ; %si <- 0
; push 0x0100
movw $0x0100, %di
push %di
xor %di, %di
ret ; pop 0x0100 from stack and jmp to 0x0100
exercise: write a C program that outputs its source code
possible in any (Turing-complete) programming language
called a “quine”
#include <stdio.h>
char*x="int main(){
printf(p,10,34,x,34,10,34,p,34,10,x,10);
}";
char*p="#include <stdio.h>%c
char*x=%c%s%c;%cchar*p=%c%s%c;
%c%s%c";
int main(){
printf(p,10,34,x,34,10,34,p,34,10,x,10);
}
some line wrapping for readability — shouldn’t be in actual quine
printf to fill template
10=newline, 34=double quote, p=template,x=constant string
template filled in by printf
#include <stdio.h>
int main(void) {
char buffer[1024];
FILE *f = fopen("quine.c", "r");
size_t bytes = fread(buffer, 1, sizeof(buffer), f);
fwrite(buffer, 1, bytes, stdout);
return 0;
}
mov $0x8f9, %si ; %si <- beginning of virus data
...
mov $0x288, %cx ; %cx <- length of virus
mov $0x40, %ah ; %ah <- system call # for write (for int 0x21)
mov %si, %dx
sub $0x1f9, %dx ; %dx <- beginning of virus code
int 0x21 ; make write system call
; %ah = operation to do (write)
; %dx = pointer to data to write
; %cx = length of data to write
// set virus data address:
0x700: mov $0x8f9, %si
// machine code: be f9 08
// be: opcode
// f9 08: immediate
...
// %ax contains file length (of file to infect)
mov %ax, %cx
...
add $0x2f9, %cx
mov %si, %di
sub $0x1f7, %di // %di <- 0x701
mov %cx, (%di) // update mov instruction
...
Vienna design: %si contains “base address”
problem: adjusting it when infecting
solution: overwrite immediate value in instruction that sets %si
new value will be written to infected executable
mov in memoryjmp at top is generated0x700: mov $0x8f9, %si
...
; %ax contains file length (of file to infect)
mov %ax, %cx
sub $3, %ax
; update template jmp instruction
mov %ax, 0xe(%si) ; 0xe + %si = 0x907
...
mov $40, %ah
mov $3, %cx
mov %si, %dx
add $0xD, %dx ; dx <- 0x906
int 0x21 // system call: write 3 bytes from 0x906
...
0x906: e9 fd 05 ; jmp PC+0x05FD
0000000000000000 <next-0x3>:
0: e8 00 00 call 3 <next>
target addresses encoded relatively
pushes return address (next) onto stack
0000000000000003 <next>:
3: 59 pop %cx
cx containts address of the pop instruction
viruses insert code in other programs
Vienna’s choice: end of executables
search for .COM executables on system
considerations for other options:
spreading: identifying useful files to infect
stealth: avoiding detection
...
403788: e9 59 0c 00 00 jmpq 4043e6 <__sprintf_chk@plt+0x1a06>
40378d: 0f 1f 00 nopl (%rax)
403790: ba 05 00 00 00 mov $0x5,%edx
...
403ab9: eb 4d jmp 403b08 <__sprintf_chk@plt+0x1128>
403abb: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
403ac0: 4d 8b 7f 08 mov 0x8(%r15),%r15
...
404a01: c3 retq
404a02: 0f 1f 40 00 nopl 0x0(%rax)
404a06: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
404a0d: 00 00 00
...
could fill with anything — unreachable
some platforms: filled with crashing instructions
why not in example? assembler just told to align instruction
probably better for CPU to fill with some instruction; Intel manual:
.dynamic section — data structure used by dynamic linker:
Contents of section .dynamic:
600e28 01000000 00000000 01000000 00000000 ................
... several non-empty entries ...
600f88 f0ffff6f 00000000 56034000 00000000 ...o....V.@.....
VERSYM (required library version info at) 0x400356
600f98 00000000 00000000 00000000 00000000 ................
NULL --- end of linker info
600fa8 00000000 00000000 00000000 00000000 ................
unused! (and below)
600fb8 00000000 00000000 00000000 00000000 ................
600fc8 00000000 00000000 00000000 00000000 ................
600fd8 00000000 00000000 00000000 00000000 ................
600fe8 00000000 00000000 00000000 00000000 ................
gaps between sections
reassembling code avoids worrying about splitting instructions
objdump -x /bin/ls: LOAD off 0x0000000000004000 vaddr 0x0000000000004000 paddr 0x0000000000004000 align 2**12
filesz 0x0000000000013091 memsz 0x0000000000013091 flags r-x
LOAD off 0x0000000000018000 vaddr 0x0000000000018000 paddr 0x0000000000018000 align 2**12
filesz 0x0000000000007458 memsz 0x0000000000007458 flags r--
running /bin/ls in gdb:
(gdb) info proc map
process 1178818
Mapped address spaces:
Start Addr End Addr Size Offset Perms objfile
0x555555554000 0x555555558000 0x4000 0x0 r--p /usr/bin/ls
0x555555558000 0x55555556c000 0x14000 0x4000 r-xp /usr/bin/ls
0x55555556c000 0x555555574000 0x8000 0x18000 r--p /usr/bin/ls
....
0x13091 bytes, loaded 0x14000
0x18000, not 0x17091bootloader in first sector (512 bytes) of device
(along with partition information)
code in BIOS to copy bootloader into RAM, start running
bootloader responsible for disk I/O etc.
BIOS-based boot is going away (slowly)
new thing: UEFI (Universal Extensible Firmware Interface)
like BIOS:
unlike BIOS:
malware wants to keep doing stuff
one option — background process (easy on modern OSs)
also stealthy options:
/bin/ls: file format elf64-x86-64
/bin/ls
architecture: i386:x86-64, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x00000000004049a0
404a01: c3 retq
404a02: 0f 1f 40 00 nopl 0x0(%rax)
becomes
404a01: e9 XX XX XX XX jmpq YYYYYYY
do_some_floating_point_stuff:
movss float_one(%rip), %xmm0
...
retq
float_one: .float 1
00 00 80 3f) is not valid machine codeone idea: replace calls
normal x86 call FOO:
E8 (32-bit value: PC - address of foo)could look for E8 in code — lots of false positives
foo:
push %ebp // push old frame pointer
// 0x55
mov %esp, %ebp // set frame pointer to stack pointer
// 0x89 0xec
e8 refers to real function
ENDBR64 (hex f3 0f 1e fa)mprotect, Windows: VirtualProtectputs, evilvirushow to hide:
how to run: