Sunday, 20 January 2013

How to hex a malware and make a builder

Hello, a tutorial made some weeks ago on Trojanforge, got the idea to write after seeing this:

And also because malware builders seems to be fashion these days.
When malware writers give only bins and no builder, the only way to fuck them up is to codecave the bin for make it do what we want.
You have many advantages because you can remove bugs, add features... you are free.
For make this, you will need: .ollydbg, HexDecCharEditor v1.02 (or any other hex editor) and a minimum of intelligence.

For the coding part i've choose 2 languages: Visual Basic 6 and Assembly with masm32 and WinASM as IDE. (two extreme, one high and one low-level language)

So let's start.
The first step is to locate things you need to modify inside the malware (e.g: gate urls, timers, enc keys)
For malware, do to ethical issue i will chose a simple unNagMe coded fastly in ASM.
And like that you can try to modify things without the fear of being infected.

This executable can be downloaded with both sources code at the end of this post.

Run Ollydbg and load the executable inside to have a look and see what the code look's like

Pretty simple with a good zone of zero filled bytes, and we see strings are pointing to 0x403000 and 0x403023
We need to find a zone with enought nullbytes to insert our url, the zero filled place on the screenshot can be good but i've choose to add my strings under original one.
This green place can be good and used, i've used HexDecCharEditor to find it:

Now that we have found a place for our URL we need to modify the executable to make it go on our string.

(843, VA=0x403043)
Double click on the line and modify the code, then: Right Click>Copy to executable>All modification
A window appear: Click 'Copy all' then another window appear, right click on it and click "Save file".

Everything is cool now.
We just need to code a program who will edit our binary at 0x403043
For that i will modify some of my old VB6 and ASM codes

Basic interface:

Please note that for Visual Basic i've used a commonDialog mean the program is dependent of one ocx: COMDLG32.
The code for boths are a bit hardcoded and can be improved but that work and it's enought for me.
One the file is builded the hexed version is named "Malware.exe.ViR"

ASM Code, patch.asm:
.model  flat, stdcall
option  casemap :none

include         /masm32/macros/macros.asm
includelib      user32.lib
includelib      kernel32.lib
includelib      shell32.lib
includelib      advapi32.lib
includelib      gdi32.lib
includelib      comctl32.lib
includelib      comdlg32.lib
includelib      masm32.lib
includelib winmm.lib

DlgProc               Proto     :DWORD,:DWORD,:DWORD,:DWORD
List                  Proto     :DWORD,:DWORD
Patch                 Proto     :DWORD
Scan                  Proto


ProgId          db "RED WM",0            
TargetName      equ "- SomeAppName vX.XX.XXX -",0                          
TargetName2     equ "ExampleApp.exe",0                                      
NameofTarget    db TargetName,0
SecondN     db "Malware.exe.ViR",0  
Sequence        db  00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h
                db  00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h
                db  00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h
                db  00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h
WBuffer         db  256 dup(00)
PatchOffset     dd  00000843h   ; VA=403043


StartNfo     db "* Close the application if open.",0
StartNfo2    db "* Just apply the patch.",0
StartNfo3    db "* Waiting for your order ...",0
Backup       db "* Offsets patched, Creating Backup...",0
Success      db "* Target patched successfully, n-j0y ;)",0
Version      db "* Invalid File version, or already patched.",0
Nothing      db "* Nothing patched, Aborted*",0
Searching    db "* Analysing offsets...",0
ReadError    db "* Can't Read the file.",0
WriteError   db "* Nothing patched, Aborted*",0
OpenError    db "* File Already open, close the file and retry.",0
FileFilter  db  TargetName2,0

hInstance       HINSTANCE   ?
hTarget         HINSTANCE   ?
hTargetMap      HINSTANCE   ?
ofn             OPENFILENAME    <>
RBuffer         dd      ?
BytesRead       db      ?
BytesWritten    db      ?
pMapView        dd      ?
FileSize        dd      ?
SearchOffset    dd      ?

hMapping        dd      ?
pMapping        dd      ?
TargetN         db      512 dup(?)
inBytes         db      512 dup(?)

alen            dd ?

IDD_CRACKME     equ 101
IDC_PATCH       equ 2001
IDC_EXIT       equ 2002
IDC_ABOUT       equ 2003
icon            equ 2000
IDC_TARGET     equ 2006
IDC_LISTBOX     equ 1002
IDC_BYTES       equ 2012

    invoke GetModuleHandle, NULL
    mov    hInstance,eax
    invoke InitCommonControls
    invoke DialogBoxParam, hInstance, IDD_CRACKME, NULL, addr DlgProc, NULL
    invoke ExitProcess,eax

align dword
DlgProc proc hWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
    ;-------- Load Cursor ---------
    invoke LoadCursor,hInstance,300
    invoke SetCursor,eax
    .if uMsg == WM_INITDIALOG
    invoke LoadIcon,hInstance,icon
    invoke SendMessage,hWnd,WM_SETICON,ICON_SMALL, eax
    invoke GetDlgItem,hWnd,IDC_BYTES
    invoke SendMessage, eax, EM_SETLIMITTEXT,64,0
    invoke SendMessage,hWnd,WM_SETICON,1,eax   
    invoke SetWindowText,hWnd, addr ProgId
    invoke SetDlgItemText,hWnd,IDC_TARGET,addr NameofTarget
    invoke List,hWnd,addr StartNfo
    invoke List,hWnd,addr StartNfo2
    invoke List,hWnd,addr StartNfo3
    invoke SetFocus,eax
.elseif uMsg == WM_COMMAND
       mov eax,wParam
.if eax==IDC_PATCH
        invoke GetDlgItemText,hWnd,IDC_BYTES,addr WBuffer,sizeof WBuffer
        .if eax == 0 || eax > 64
            invoke List,hWnd,chr$("URL field is either empty or has more than 64 chars!")
            mov ofn.lStructSize,SIZEOF ofn
            mov ofn.lpstrFilter,offset FileFilter
            mov ofn.lpstrFile,offset TargetN
            mov ofn.nMaxFile,512
            invoke GetOpenFileName,addr ofn
            .if eax==TRUE
                invoke CopyFile, addr TargetN, addr SecondN,TRUE
                invoke Patch,hWnd
.elseif eax==IDC_EXIT
    invoke SendMessage,hWnd,WM_CLOSE,0,0
.elseif eax==IDC_ABOUT
    invoke MessageBox,hWnd,chr$("** RED CREW 2013"),chr$("About"),MB_ICONINFORMATION
    .if uMsg==WM_RBUTTONDOWN
            invoke ShowWindow,hWnd,SW_MINIMIZE
.if uMsg == WM_CLOSE
        invoke  EndDialog, hWnd, 0

    xor eax,eax

DlgProc endp

List proc hWnd:HWND, pMsg:DWORD
    invoke SendDlgItemMessage,hWnd,IDC_LISTBOX,LB_ADDSTRING,0,pMsg
    invoke SendDlgItemMessage,hWnd,IDC_LISTBOX,WM_VSCROLL,SB_BOTTOM,0
List EndP

Patch proc hWnd:HWND
    invoke GetFileAttributes,addr SecondN
        invoke SetFileAttributes,addr SecondN,FILE_ATTRIBUTE_NORMAL
    invoke CreateFile,addr SecondN,\
        mov hTarget,eax
            invoke List,hWnd,addr Searching
        invoke SetFilePointer,hTarget,PatchOffset,NULL,FILE_BEGIN
        invoke ReadFile,hTarget,addr RBuffer,64,addr BytesRead,NULL
        .if BytesRead==64
            mov eax,dword ptr [RBuffer]
            .if eax==dword ptr [Sequence]
                 invoke SetFilePointer,hTarget,PatchOffset,NULL,FILE_BEGIN 
            ;    invoke CopyFile, addr TargetN, addr BackupName,TRUE
                 invoke WriteFile,hTarget,addr WBuffer,64,addr BytesWritten,NULL
                .if BytesWritten==64
                 invoke List,hWnd,addr Backup
                 invoke List,hWnd,addr Success
                 .elseif eax==dword ptr [WBuffer]
                invoke List,hWnd,addr Version
                invoke List,hWnd,addr Nothing
        invoke List,hWnd,addr Searching
        invoke List,hWnd,addr OpenError
        invoke List,hWnd,addr Nothing
    invoke CloseHandle,hTarget
Patch EndP

end xstart

;This Resource Script was generated by WinAsm Studio.

#define IDC_STATIC2011 2011
#define IDC_BYTES 2012
#define IDC_GROUPBOX2013 2013
#define IDC_GROUPBOX2015 2015
#define IDC_GROUPBOX2016 2016

1 24 DISCARDABLE "manifest.xml"
300 CURSOR DISCARDABLE "Crystal Clear arrow.cur"

101 DIALOGEX 0,0,311,136
FONT 8,"MS Sans Serif"
STYLE 0x80c00880
EXSTYLE 0x00000008
    CONTROL "RED CREW",IDC_GROUPBOX2013,"Button",0x50000007,3,3,304,130,0x00000000
    CONTROL "Control",IDC_GROUPBOX2016,"Button",0x50000007,230,65,64,59,0x00000000
    CONTROL "Status",IDC_GROUPBOX2015,"Button",0x50000007,13,65,214,59,0x00000000
    CONTROL "Patch",2001,"Button",0x50010000,240,77,42,13,0x00000000
    CONTROL "About",2003,"Button",0x50010000,240,92,43,13,0x00000000
    CONTROL "Target:",2004,"Static",0x50000001,13,15,23,10,0x00000000
    CONTROL "",2006,"Edit",0x50010881,13,25,281,11,0x00000200
    CONTROL "Exit",2002,"Button",0x50010000,240,108,43,13,0x00000000
    CONTROL "",1002,"ListBox",0x50010140,20,77,201,38,0x00000200
    CONTROL "URL:",IDC_STATIC2011,"Static",0x50000000,13,40,41,10,0x00000000
    CONTROL "",IDC_BYTES,"Edit",0x50010081,13,49,281,11,0x00000200

102 DIALOGEX 10,10,206,113
FONT 8,"Tahoma"
STYLE 0x90480800
EXSTYLE 0x00000000

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity version="" processorArchitecture="x86" name="NoName" type="win32"/>
      <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="" processorArchitecture="x86" publicKeyToken="6595b64144ccf1df" language="*"/>

The end.
Don't hesitate to show examples of codes if you are motivated.
No password on archive because nothing is infected.

And if you want some fun: InjectMe #1, InjectMe #2

Other tutorials (in French sorry)
Etude sur l'indétection du Server de Bifrost 1.2d auprés des Antivirus
ShmeitCorp Memento 6: StartClean Patcher

Package download:


  1. Well done, thanks you.

  2. I like your blog in general, but why are you educating the script kiddies?

  3. Just curious to see what they can do and with wich one

    1. not educating the scrip kiddies alone he is educating researchers too . cant you see the positive side of the tutorial as well?

    2. @Anonymous He was referring to himself...

  4. ASM code is commented well-cleared but what about the VB6 code? How change the offset to patch? (Sorry I'm not a vb dev but I'm curious).

    Thanks Xyl'!