My good friend Colin, who has taught me literally everything I know about RE, wanted to challenge me with a static analysis test. During my process of learning RE I have relied heavily, if not entirely, on dynamic analysis. While discussing the idea of some future projects he agreed I needed more time and practice with static analysis. So Colin built a simple binary for me to reverse, using only static analysis.

I started by opening it in x64dbg and taking a look at main.

The first thing I see is a call to GetForegroundWindow which takes no parameters and returns a handle to the foreground window as a HWND. After GetForegroundWindow is called, the handle is stored in a local variable at [ebp-100]. Next there’s a comparison on the HWND and 0, if it’s equal to 0 it’s going to jump to the bottom, past all the other calls, and return early. This looks like it’s checking to see if the HWND was null.

So far my code looks like this.

#include <Windows.h>

int main()
{
    HWND hWnd = GetForegroundWindow();

    if (hWnd != NULL)
    {
        // More code goes here.
    }
}

Next we have a call to GetWindowTextA which copies the text of a window’s title bar into a buffer. It takes three parameters: a handle to a window, a buffer to receive the text, and the maximum number of characters to copy into the buffer. These are pushed in the reverse order so first we see 0xFF which is the number of characters to copy, then the buffer, and lastly the handle to the window.

So now my code looks like this.

#include <Windows.h>

int main()
{
    HWND hWnd = GetForegroundWindow();

    if (hWnd != NULL)
    {
        char buffer[0xFF] = { 0 };
        GetWindowTextA(hWnd, buffer, 0xFF);
    }
}

This next part was definitely the trickiest section of this test. We have the number 45464143 being moved into the buffer at [ebp-100]. The buffer is currently an array of characters, which is the same thing as a char*. To get the value of 45464143 into the buffer we need to dereference the buffer. But a character is only one byte and our number is the size of an int, or four bytes. That means we also need to cast our buffer to an int so we can fit all of it in.

All that’s left is a call to SetWindowTextA that takes a handle to the window and our buffer. And our final code looks like this.

#include <Windows.h>

int main()
{
    HWND hWnd = GetForegroundWindow();

    if (hWnd != NULL)
    {
        char buffer[0xFF] = { 0 };
        GetWindowTextA(hWnd, buffer, 0xFF);
        *(int*)buffer = 0x45464143;
        SetWindowTextA(hWnd, buffer);
    }
}

The reality is that one line *(int*)buffer = 0x45464143; took me a long time to figure out how to recreate it. The first step to figuring it out was observing what the function was actually doing.

Notice how the first four letters of our window’s title is renamed to “CAFE”. That shows me the number wasn’t just any number, it was the hex representation of the ASCII characters “CAFE”.

Once I had that knowledge the next thing I did was recreate the functionality using a for loop, assigning the individual characters of “CAFE” into the first four positions of the buffer array. That was a suitable answer for the task, as we were just trying to recreate the functionality and not match the assembly byte for byte.

However I wasn’t pleased with that answer, I really wanted to recreate the assembly as accurately as I could. I knew I had to dereference the pointer to get to the value of buffer, but I was only getting the first letter of “CAFE” and not the entire thing. After a while, I realized I made a crucial mistake in forgetting that a char is only one byte where an int is four bytes. I was trying to assign the value of a char with an int, and that just wont work. Then I added in the type cast to an int and was satisfied with my answer.

Here is my final answer, in assembly.

And here is Colin’s source code.

#include <Windows.h>

int main()
{
    char windowText[255];

    auto hWnd = GetForegroundWindow();

    if (hWnd)
    {
        GetWindowTextA(hWnd, windowText, sizeof(windowText));

        *(unsigned int*)windowText = 0x45464143;

        SetWindowTextA(hWnd, windowText);
    }

    return 0;
}

Last modified: June 7, 2019