Showing posts with label c. Show all posts
Showing posts with label c. Show all posts

Friday, May 20, 2022

Windows Objects

Objects in windows are referred as kernel objects. They provide a link or an way to use any objects functionality according with the object itself. There are many types of objects in Window, we can use Sysinternals WinObj in the side menu view you can find "ObjectTypes". This list shows a variety of objects that can be created by us using Windows API. 

  • Objects like: mutex, semaphore, file, process, thread, timer. Can be created by the user-mode using Windows API.
  • Some other objects can be created using WDK, for device driver.
  • And the undocumented used directly by the kernel itself.

All objects can be accessed by it's relative HANDLE. The HANDLE it's private for a process context. It's important to say that HANDLE are basically number IDs for it's reference kernel object structure. So when we open a file we get a HANDLE back, then we use this ID so the kernel can locate this file on "low-levels", hardware managing and etc. 

We always has to CloseHandle after we don't need it anymore this makes a code background (memory and so on) clean and concise with no loose ends. HANDLEs are always 4 bytes long for alignment purposes. Easy and concise memory access. When a HANDLE creation is not successful the the handle it self return NULL(0), except when it's CreateFile that returns INVALID_HANDLE_VALUE(-1).

The function GetLasError is the function to go if any errors occur during the creation or opening of any object probably it will be specified why in the function mentioned.

When you create a program that creates a CreateMutex and tries to open an instance of the same program, you will get a ERROR_ALREADY_EXIST with GetLastError function. The CreateMutex will give you an index, but if you check GetLastError it will give you already exists error.

Handles is a hold of a structure in the kernel space containing all information necessary to access the HANDLE properties. 8 bytes in 32-bits and 16 bytes in 64-bit. Each HANDLE has an AccessMask that contains everything the handle can do. HANDLES has 3 main flags not mot used: Inheritance, Protect from close and Audit on close. AccessMask is a bitmask that is turned on of off by "1" bit in its data. The  AccessMask can be informed at a creation of a Process, for example:


HANDLE hProcess = ::OpenProcess(PROCESS_TERMINATE, FALSE, processId);

The AccessMask is marked by PROCESS_TERMINATE and can be "unified" with the character "|" to append other process access. A process list of access can be viewed here.


::OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION, FALSE, processId);

 The 3 flags there are used like:

  • Inheritance
    • Used for share handle object between processes. Used when they are needed together to some use.
  • Audit on close
    • Rarely used. Indicates whether an audit entry would be written when the handle get closed.
  • Protect from close
    • Prevents handle from been closed by CloseHandle, returning ERRO_INVALID_HANDLE when tried to be closed. Rarely used and useful.

We can change the flag information by calling  SetHandleInformation.


#define HANDLE_FLAG_INHERIT             0x00000001
#define HANDLE_FLAG_PROTECT_FROM_CLOSE  0x00000002 

::SetHandleInformation(h, HANDLE_FLAG_PROTECT_FROM_CLOSE, HANDLE_FLAG_PROTECT_FROM_CLOSE);

    //To remove it
::SetHandleInformation(h, HANDLE_FLAG_PROTECT_FROM_CLOSE, 0);
We also have the Pseudo Handles, special values that are not closable and always respond with an specific value.

  • GetCurrentProcess()(-1): Return a pseudo handle to current process.
  • GetCurrentThread()(-2): Return pseud handle to current thread.
  • GetCurrentThreadToken()(-5): Return pseudo-handle to then token of the calling thread.
  • GetCurrentThreadEffectiveToken()(-6): Return pseudo handle to the effective token of calling thread (If not token is present in thread, process's is return instead).

Creating Objects 

All objects needs a LP_SECURITY_ATTRIBUTES structure tha tells Windows API which type of access this object will have. 
 

typedef struct _SECURITY_ATTRIBUTES {
    DWORD nLength;
    LPVOID lpSecurityDescriptor;
    BOOL bInheritHandle;
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES;
   

The nLenght is a common practice of Windows API to set the structure size in it, so when new version is out the API only will read the stipulated size, then maintaining the old versions compatibility.

The lpSecurityDescriptor is a pointer to a security descriptor this is the core member, that set in the HANDLE structure what it can really do with the open object.

The bInheritHandle is a previous mentioned flag Inheritance, but here we don't need to use SetHandleInformation to set it's value, we can just set it here if it's necessary.

In general when using, for example, CreateMutex:


HANDLE CreateMutex(
    _In_opt_ LPSECURITY_ATTRIBUTES lpMutexAttributes,
    _In_ BOOL bInitialOwner,
    _In_opt_ LPCTSTR lpName
);
   

We just set it to nullptr, and the object assumes it's defaults from the process itself.

Sharing objects

Object name while creating a new object that receive "name" in it's parameters and already exists, the create function will just open the handle to it, the create function would not give any error if everything is right and only will return the object that is already created. As said before we can check this information calling GetLastError will give us the ALREADY_CREATED error. Then the SECURITY_ATTRIBUTES of this attempt to create a new object will NOT affect the already created object.

There are a few ways to share objects through processes:

  • By name
  • By handle inheritance
  • By duplicating handle

When you need to share by name, you just have to create a same type of object, and one that accepts "name" parameter. For example to share a Memory Mapped File. You just has to create in one process and create with the same exact name in another one.


HANDLE hSharedMemory = ::CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, 1 << 12, L"ASharedMemory");
   

You just need to use the same line of code, if this object name already exists the API you return a ID that points do the already created object, so making it easy to read from the same space in memory and share the object through processes.

 In this specific case we could use the sequence to write or read from it.


void* buffer = ::MapViewOfFile(hShareMemory, FILE_MAP_WRITE, 0, 0, 0);
::wcscpy_s((PWSTR)buffer, someSize, someData);
void* buffer = ::MapViewOfFile(m_hSharedMem, FILE_MAP_READ, 0, 0, 0);
   

 The last, MAP_READ, we could copy for a local variable or we could just use the buffer in code.

Duplicate handle is also a valid way to share objects. Can be the best option in case the object creation doesn't offers a name parameter. The way to do it is to use the function DuplicateHandle.


BOOL DuplicateHandle(
    _In_ HANDLE hSourceProcessHandle,
    _In_ HANDLE hSourceHandle,
    _In_ HANDLE hTargetProcessHandle,
    _Outptr_ LPHANDLE lpTargetHandle,
    _In_ DWORD dwDesiredAccess,
    _In_ BOOL bInheritHandle,
    _In_ DWORD dwOptions
);
   

hSourceProcessHandle must have the access maks PROCESS_DUP_HANDLE when it was opened in order to the duplication of handles works fine.
dwDesiredAccess This is the mask access to the new handle. In case the DUPLICA_SAME_ACCES is informed in dwOptions, then this parameter is ignored.
dwOptions aside from the one above, we can inform DUPLICATE_CLOSE_SOURCE, this makes the handle on source process to be closed after duplication. I listed just the important parameters only. 

In the same pack of kernel objects we also have some common objects, user objects and GDI objects.

User Objects

 
The user objects can be divided between:
  • Windows - HWND
  • Menus - HMENU
  • Hooks - HHOOK

GDI Objects

 
Graphic Device Interface (GDI) is the classic graphical API in Windows. Even there are more recent ones in use like, Direct2D, GDI is still use. GDI common objects:
  • Device Context - HDC
  • Pen - HPEN
  • Brush - HBRUSH
  • Bitmap - HBITMAP
Important points:
  • Handles are valid only in the process where they were created
  • Cannot be shared between processes
This topic is just a resume and easy access for me to Windows Objects, as I read about it.

Friday, September 1, 2017

Solving the first exercise

Hello, there!

In this post we will reverse engineering the exercise-program that I left in my previous post about compiling C programs.  I tried to make well explained and objective. So any question let me know.

Prerequisites:
In the end of the post linked above there is a code that we are going to use in this post. Compile it and let's begin. Tools in this post:
In my last post I left an exercise (simple one) that the goal was to reach the "Secret Stuff!". In this post I will show two ways to do it. It's very simple program coded in C. I assume that already have compiled the program as the link in the prerequisite.

First I ran it to see what happens:

Fig1 - Running the program

Nothing much, just a simple "Not Valid". Well I will run the strings.exe from SysInternals to see if we can find something interesting. I configured my strings program in the Path environment variable to be easy to execute. Take some time and look closely to anything that could be interesting. There are a lot of strings here, but the 90% is standard, besides this doesn't seem encrypted. Taking a time rolling up and down, I could find some interesting strings:

Fig2 - Strings the program

Well I see that I will have to type some password, but when I first ran it nothing was asked to me. Why this ?. And we have the secret stuff too, so we just began with it since our goal is to reach that part, we deal with password in the way to it if we had too.

We could open in some software like CFF Explorer to dig into the imports and so on, but doesn't seem necessary at this point. So let's open it in the IDA Pro and see if we can find anything interesting. With the program opened in the IDA Pro let's seek for our goal in the tab Strings, click in the tab and search for the "You reach the secret stuff!!", then double click in the line with the string. IDA sent us to the part of the section rdata in the offset that starts the string. We have to click in the offset name aYouReachTheSec and press the X key, then we can choose the references for this offset, since we just have one let's double click it. We were drove to a function that uses this string sub_401517, we can click on it's name and press N to rename it, I renamed to SecretSub. Ok, this would be enough to crack it. I will show two manners to do it, cracking it(Patching) and bypassing it. To bypass we just have to find how to reach the secret stuff without hardcode/patch the binary.


Fig3 - String offset in the section rdata


Bypassing the binary


To bypass the binary first we have to find how the binary reach this SecretSub in normal way, so click in the name of the sub and press X to find the references to this sub. We only find one reference:

Fig4 - Main flow

As we can see we have a little piece of the program that asks for some password using the scanf (C API) to get the password, call sub_401460 and right after uses a cmp eax, 1. We can deduce that we get the password and then sub_401460 will check for the password to see if it is right and return to eax if the password is right or not. Let's see how the binary validates the password double clicking in the sub_401460. We were drove into the sub and I already rename the sub to PasswordCheck making it easy to identify.

Fig5 - Password checking

We can see some loops, some ifs and in the end of the sub we have only one piece of code that will drive us to the good end (mov eax, 1), the other pieces just print "Not Valid" in the screen. The first part is interesting, many hex values stock in variables at the first piece of code, we will look at it after. IDA name the variables for us to make our work more easy, this variables are just offsets in the stack for example [ebp+var_c] without the IDA would be [ebp-C], so IDA put variable names in the offset to make our lives easier, we can even rename the variables clinking in their names and pressing N to make it more easy to read the code.

After looking a little at this code we are able to identify that the first part seems like a counter adding in the variable var_10 to be compared in cmp [ebp+var_10],14h , the size in this variable has to be lower than 14h (decimal 20) if it was larger then we got a "Not valid" message.

We can deduce to this point that the password must be under 20 characters. In the next block it uses the variables var_c (counter) and var_1B (string reference), the var_c is an index reference to the string array for both the argument arg_0 (types password) and the var_1B (hardcoded password). It compares byte per byte from both variables to check if the password matches. So we can take the var_1B till var_11 to get the expected password. If we get the whole and put it together we can convert hexadecimal to unicode characters, but we have to keep in mind that since the value is in the stack it is disposed in little-endian order, thus to convert it we must write them in the reverse order like 3332312D3132332D323331 converting this we get "321-123-231". Now we have the password, but if we run it we can't get in the part to type the password, so we have to dig a little more. Let's back a little and see what it have to does to reach the part that asks for the password.

As we can see in the Fig4 there is a cmp with the arg_0 in the main function and right after a conditional jump JG, since this program was written in C we know that in the main function the first argument by default is the amount of arguments passed to the program to execute. If you ran the program in the CMD the first argument will be always the complete path to the program that is been executed. Therefore we must have more than one argument when execute this program, to do this we just add any text after the program name like ">main.exe newargument" if you execute like this we can bypass this part and reach the password part. Let's try it:

Fig6 - Program bypassed

Voilá! We did it, we bypassed the exercise without patch anything.

Patching the binary


Now let's do a quick and functional patch to get this working without type anything. We want to reach the secret stuff without efforts, execute the program and reach it. How can we do it, now we know the address that calls the SecretSub, we just have to alter that conditional jump JG that was made right after the comparative in the program's argument and JMP directly to the call to the SecretSub. We can do this using the x64dbg. Open the program in the debugger reach the address using the CTRL+G in the address 40153E and press space bar to patch this line. To work properly we can't simple call or jump inside the secret stuff because the program must return to properly exits the execution, then we simply jump directly to the right call using a unconditional jump jmp 0x40158E. Press CTRL+P to open the patches click to patch file and choose a name to the new executable and save it. Now try to run it.

Fig7 - Patched program

Voilá! Now we access the secret stuff without have to type anything.

Well that is it folks! This program was quite simple with no anti-technique at all. In the next posts I will try to bring more difficult exercises. :) Thank you for you time and see you soon! Any questions at all please let me know! :)

Thanks! Best regards!

Saturday, July 8, 2017

Writing and compiling a program in C

Hello there!

Today I want to bring a short post where I will show you how to write a program in C and compile it with GCC on Windows. This post will be useful, because we will need to compile the sources that I will bring on future technical posts. My goal is not to teach C programming, there is a lot of content about it on the web. Of course that I will help you along the posts with references about the code sources.

I recommend reading the previous topcis:



The GCC


Since I will not bring the executable here instead just the C code for you to compile on your own environment. In this way you can understand better how C code turns into Assembly code. Like a said in the previous topics, it's important to know programming in reverse engineering even if somebody tells you that isn't. There is no ultimate truth, so I'm open to any comment, tips or criticisms.

Well, let's do it! First we have to download the GCC, I'm using the MinGW to install it. There is a lot of C compilers out there, I pick the MinGW for convenience.




Download and install it at "C:\mingw" to be easy to access. Skip any checks to install components, just finish the installation. We will install the GCC via console on the next step. Once you have installed it, open the CMD or PowerShell goes to the mingw folder.


cd c:\mingw\bin
mingw-get.exe install mingw32-gcc-bin

We will only install the bin component, because we only want to compile our code. After the download process by the MinGW we are good to go, to write and compile our program.

To use the GCC directly, I mean through any folder in console you have to add the path of GCC to the Environment Path property.



GCC compiles our source with some initialization code that is default for every compilation, as I could see so far it starts to write the assembly from given address (0x401460), this is for the standard compilation setting. Let's see it in the next example. I wrote this simple code in C to test our GCC whether it's ok or not:


#include <stdio.h>

int main(){
   
    printf("Hello There. VerseInversing!\n");
   
    return 0;
}

Copy the code below on your favorite editor, save it like "sample.c" on C:/. Now open the console and run the command:


cd C:\
gcc sample.c -o sample

If everything it's ok you should see a sample.exe created on C:\. Just type it on console and execute it.


./sample.exe

Cool uh ? haha

Well, now we have to see how the assembly was generated. I was using the OllyDbg, but since the x64dbg has becoming very popular I'm giving it a try. It's a nice debug tool updated very often, have many features embed in it and many other good things. Download at:




Program loading (Very simple approach)


Before we get our hands dirty, let's see basically how the programming execution works. So first of all I assuming that you read the previous topics. So, to execute a program (binary file) the windows needs to load this file into memory so it takes the file and simply put it into the memory. Then each file type is interpreted in different ways when loaded into memory. The executable file have the header with key information that let the windows load it and execute it properly.

So the executable file always have the PE (Portable executable) header, without it the OS just can't load it. In the PE Header we have vital information that will help our analysis. Is this same information that let the debugger loads it and show us all the information that will help us on the debugging process.

In this PE Header we have many information, like the EntryPoint. EntryPoint like it's name, is the offset where the execution must to begin. This offset belong to the (code, text) section where all the code of our program is in. Again, everything on the file is hex data, but when you put this data on code or text section the OS reads it as instructions to CPU execute. All the rest is hex data too, but it is interpreted in a different way. As I said all depends on how you want to interpret information.

So as I said the executable mainly uses the OS to run, so it will need the libraries on the OS to run it's code. Unless the coder uses the ordinal number to call the API, it's easy to see which api the program uses by looking at the .idata section. IDATA stands for "Import Data" that is the imports the executable do to use on the execution.

On windows each DLL library has specific functionality so you can basically use some program like  CFF Explorer to look at the imports of the PE and google each DLL to see the specifics of each one. In our case it uses the KERNEL32.dll and msvcrt.dll. KERNEL32.dll it's pretty basic with core functions, it's very very common. msvcrt.dll it's the library of C on Windows, so as we are using C it make sense to importing it.

Anyway this is subject to another post, but I just doing a little intro on it. Let's continue our debugging.

Let's debug


After you have downloaded and installed it. Let's open our fresh compiled program. Well, it starts little different from others, not at all.. but a little.
It started at ntdll.dll module, but it's already set the breakpoint on the entry point of the executable (EntryPoint information is in the PE Header).

As I said before the program imports some DLLs to uses it's functionality. This DLLs run with our executable so each one of these DLLs and also our executable is a module running. In this case the ntdll.dll was imported by KERNEL32.dll because the the DLL itself uses the ntdll.dll that does some interface with the kernel.

Let's continue. In the x64dbg goes to the Breakpoints tab and look at the breakpoints:



Shortcuts used in this post:


  • F9: Run the program to the end if it doesn't find any breakpoint ahead.
  • F8: Step by step or Line by line.
  • F7: Step into. If there is any CALL instruction you are going inside the CALL. If you F8 then you jump to the next line and skip the CALL.


Ignore the TLS Callback for now, we will not need it in this topic. To do this you go to Options=>Preferences=>[Tab]Events and uncheck the "TLS Callbacks*". I will bring this in the future posts. You can uncheck it or you can simply ignore it skipping with F9.

As you can see the address 0x4012E0 holds our entry point, so lets play until it stops on that address. Press F9 until you reach the address. This is the entry point on programs compiled with GCC, so our program starts after all the initialization code. My tip is to step through it to familiarize with the debugger.

But to make it shorter the call for our program block is on 0x401280 with a CALL instruction to the address 0x401460 (this is generally where the GCC starts to write our program assembly).



So let's do a little analysis. First it set the stack frame (see Assembly Basics) then it enlarges the stack frame by doing an AND followed by a SUB, then it calls a sample.sub_401970 at 0x401469 it's only check for some value at address 0x407028. If you go to the Memory tab you can see that (this information came from PE Header) the address 0x407000 is of the section .bss (uninitialized data), anyway doesn't do anything crucial and we know that, because we write it.

After this step, it move the address 0x405064 to the stack directly it doesn't uses any register to keep this value, it just MOV to the stack and call the PUTS API from the C library of the Windows. Now, why it uses puts if we write printf ? And why it calling from sample.puts ?

First question, if you see the difference from puts to printf you see why it uses the puts. Reference to the puts:




As you can see, the puts receives a pointer to a string then it put a newline character at the end of the string and that was exactly what we did in our code, but with printf. So the GCC just saw it and make it better.

Second question, if you press F7 you will step into the CALL and will see that inside the call it's just a Table JUMP to the original API. No secrets.

That's it. So we could see what the compiler can do with code, it work on it to make it simpler and "faster" in it's own way. So coding and see how compiler handles our code it's good to a better understating of assembly in practice.

I coded a simple program in C that have many ways to bypass, so the goal is to the reach the ultimate function which prints "You reach the secret stuff!!". I recommend that you do not see what it does and try to understand what it is doing and how to bypass it through x64dbg (or any other debugger). I will do a post explaining how to do it and how to patch it. Consider as an exercise. (The program is buggy, I will show why on the next post)




Any doubts, comments, tips, criticism just tell me. We are all here to learn with each other. Hope that's can be useful to anyone. I will bring some other analysis here very soon. Thanks! Bye!

Windows Objects

Objects in windows are referred as kernel objects . They provide a link or an way to use any objects functionality according with the object...