Thursday, January 8, 2015

FLARE - Challenge 5


About:


This is the 5th challenge from FireEye's "FLARE On" challenge (http://flare-on.com/)


Solution:

In this challenge, the zip file contains a Windows library file.

To start, I used Hopper to look through the imported functions, thinking that I could find something interesting and work backwards from there.




The first ones I looked through messed with the registry and looked at / touched the files "c:\windows\system32\rundll32.exe" and "c:\windows\system32\svchost.dll".

I didn't find anything too interesting in those sections, so eventually I moved on to the GetAsyncKeyState function and decided to look around where it was used.

Here's the code where GetAsyncKeyState is called: (look within the 0x10009edd block)


You can see that after it returns, the control flow goes through a bunch of if/else conditionals (switch statement?) that keeps going on and on....



...and on and on...

But even though this is messy, the nice thing is that it's pretty now clear what is going on -- it's a keylogger that will call certain functions depending on which key is pressed.

While looking through what gets called within the if statements, the vast majority call sub_10001060, which seems to clear a bunch of global variables (except one, which it sets to 0x1).



Interestingly, though, some of the subroutines that get called in a few of the cases DON'T immediately call the reset/clear subroutine (sub_10001060).

For example, below, sub_10009d80 will skip over the call to sub_10001060 in certain cases, depending on the state of the global variables that sub_10001060 clears:




I took the decompiled version of all the subroutines that don't immediately call the resetting function and put them together here:


int sub_10009440() {
    if (*0x10019460 > 0x0) {
            *0x10019460 = 0x0;
            *0x10019464 = 0x1;
    }
    else {
            if (*0x100194a4 > 0x0) {
                    *0x100194a4 = 0x0;
                    *0x100194a8 = 0x1;
            }
            else {
                    sub_10001060();
            }
    }
    return 0x100141e0;
}

int sub_100094d0() {
    if (*0x10019498 > 0x0) {
            *0x10019498 = 0x0;
            *0x1001949c = 0x1;
    }
    else {
            if (*0x100194b0 > 0x0) {
                    *0x100194b0 = 0x0;
                    *0x100194b4 = 0x1;
            }
            else {
                    sub_10001060();
            }
    }
    return 0x100141f4;
}

int sub_100097d0() {
    if (*0x100194b4 > 0x0) {
            *0x100194b4 = 0x0;
            *0x100194b8 = 0x1;
    }
    else {
            if (*0x100194c4 > 0x0) {
                    *0x100194c4 = 0x0;
                    *0x100194c8 = 0x1;
            }
            else {
                    if (*0x100194d4 > 0x0) {
                            *0x100194d4 = 0x0;
                            *0x100194d8 = 0x1;
                    }
                    else {
                            sub_10001060();
                    }
            }
    }
    return 0x100142a4;
}

int sub_10009850() {
    if (*0x100194f4 > 0x0) {
            *0x100194f4 = 0x0;
            *0x100194f8 = 0x1;
    }
    else {
            sub_10001060();
    }
    return 0x100142ac;
}

int sub_10009880() {
    if (*0x10019478 > 0x0) {
            *0x10019478 = 0x0;
            *0x1001947c = 0x1;
    }
    else {
            if (*0x1001948c > 0x0) {
                    *0x1001948c = 0x0;
                    *0x10019490 = 0x1;
            }
            else {
                    if (*0x100194d0 > 0x0) {
                            *0x100194d0 = 0x0;
                            *0x100194d4 = 0x1;
                    }
                    else {
                            if (*0x100194e8 > 0x0) {
                                    *0x100194e8 = 0x0;
                                    *0x100194ec = 0x1;
                            }
                            else {
                                    sub_10001060();
                            }
                    }
            }
    }
    return 0x100142b0;
}

int sub_10009910() {
    if (*0x100194ac > 0x0) {
            *0x100194ac = 0x0;
            *0x100194b0 = 0x1;
    }
    else {
            if (*0x100194cc > 0x0) {
                    *0x100194cc = 0x0;
                    *0x100194d0 = 0x1;
            }
            else {
                    sub_10001060();
            }
    }
    return 0x100142b4;
}

int sub_10009960() {
    if (*0x100194bc > 0x0) {
            *0x100194bc = 0x0;
            *0x100194c0 = 0x1;
    }
    else {
            sub_10001060();
    }
    return 0x100142b8;
}

int sub_10009990() {
    if (*0x10019464 > 0x0) {
            *0x10019464 = 0x0;
            *0x10019468 = 0x1;
    }
    else {
            if (*0x10019468 > 0x0) {
                    *0x10019468 = 0x0;
                    *0x1001946c = 0x1;
            }
            else {
                    if (*0x10019474 > 0x0) {
                            *0x10019474 = 0x0;
                            *0x10019478 = 0x1;
                    }
                    else {
                            sub_10001060();
                    }
            }
    }
    return 0x100142bc;
}

int sub_10009a00() {
    if (*0x100194dc > 0x0) {
            *0x100194dc = 0x0;
            *0x100194e0 = 0x1;
    }
    else {
            sub_10001060();
    }
    return 0x100142c0;
}

int sub_10009a30() {
    if (*0x1001946c > 0x0) {
            *0x1001946c = 0x0;
            *0x10019470 = 0x1;
    }
    else {
            sub_10001060();
    }
    return 0x100142c4;
}

int sub_10009a70() {
    if (*0x100194a8 > 0x0) {
            *0x100194a8 = 0x0;
            *0x100194ac = 0x1;
    }
    else {
            sub_10001060();
    }
    return 0x100142cc;
}

int sub_10009aa0() {
    if (*0x10017000 > 0x0) {
            *0x10017000 = 0x0;
            *0x10019460 = 0x1;
    }
    else {
            if (*0x100194c0 > 0x0) {
                    *0x100194c0 = 0x0;
                    *0x100194c4 = 0x1;
            }
            else {
                    sub_10001060();
            }
    }
    return 0x100142d0;
}

int sub_10009b10() {
    if (*0x10019470 > 0x0) {
            *0x10019470 = 0x0;
            *0x10019474 = 0x1;
    }
    else {
            if (*0x100194e4 > 0x0) {
                    *0x100194e4 = 0x0;
                    *0x100194e8 = 0x1;
            }
            else {
                    sub_10001060();
            }
    }
    return 0x100142d8;
}

int sub_10009b60() {
    if (*0x1001947c > 0x0) {
            *0x1001947c = 0x0;
            *0x10019480 = 0x1;
    }
    else {
            if (*0x10019490 > 0x0) {
                    *0x10019490 = 0x0;
                    *0x10019494 = 0x1;
            }
            else {
                    if (*0x100194e0 > 0x0) {
                            *0x100194e0 = 0x0;
                            *0x100194e4 = 0x1;
                    }
                    else {
                            if (*0x100194ec > 0x0) {
                                    *0x100194ec = 0x0;
                                    *0x100194f0 = 0x1;
                            }
                            else {
                                    if (*0x100194f8 > 0x0) {
                                            *0x100194f8 = 0x0;
                                            *0x100194fc = 0x1;
                                    }
                                    else {
                                            sub_10001060();
                                    }
                            }
                    }
            }
    }
    return 0x100142dc;
}

int sub_10009c30() {
    if (*0x10019488 > 0x0) {
            *0x10019488 = 0x0;
            *0x1001948c = 0x1;
    }
    else {
            if (*0x100194a0 > 0x0) {
                    *0x100194a0 = 0x0;
                    *0x100194a4 = 0x1;
            }
            else {
                    if (*0x100194c8 > 0x0) {
                            *0x100194c8 = 0x0;
                            *0x100194cc = 0x1;
                    }
                    else {
                            sub_10001060();
                    }
            }
    }
    return 0x100142e8;
}

int sub_10009ca0() {
    if (*0x100194d8 > 0x0) {
            *0x100194d8 = 0x0;
            *0x100194dc = 0x1;
    }
    else {
            sub_10001060();
    }
    return 0x100142ec;
}

int sub_10009cd0() {
    if (*0x10019480 > 0x0) {
            *0x10019480 = 0x0;
            *0x10019484 = 0x1;
    }
    else {
            if (*0x10019494 > 0x0) {
                    *0x10019494 = 0x0;
                    *0x10019498 = 0x1;
            }
            else {
                    if (*0x1001949c > 0x0) {
                            *0x1001949c = 0x0;
                            *0x100194a0 = 0x1;
                    }
                    else {
                            if (*0x100194b8 > 0x0) {
                                    *0x100194b8 = 0x0;
                                    *0x100194bc = 0x1;
                            }
                            else {
                                    if (*0x100194f0 > 0x0) {
                                            *0x100194f0 = 0x0;
                                            *0x100194f4 = 0x1;
                                    }
                                    else {
                                            sub_10001060();
                                    }
                            }
                    }
            }
    }
    return 0x100142f0;
}

int sub_10009d80() {
    if (*0x10019484 > 0x0) {
            *0x10019484 = 0x0;
            *0x10019488 = 0x1;
    }
    else {
            sub_10001060();
    }
    return 0x100142f4;
}



You can see that together, they form a chain where the reset call to sub_10001060 can be avoided by calling these subroutines in a specific order.

Putting it all together (knowing that these functions will each get called when a specific key is pressed), I decided to trace back what sequence of keys would walk through the sequence that would avoid the sub_10001060 call.

I started filling out a table, starting with the address that's initialized to start at 1 (0x10017000) and looking for which subroutine expects that memory to be set to 1 (in this case, it was sub_10009aa0)


"1" address           subroutine 

0x10017000          sub_10009aa0() 

After finding the subroutine, I looked for what character was used as a return value -- in this case it was "l".

"1" address           subroutine       (ascii)

0x10017000          sub_10009aa0()        l





So this means the first character the keylogger's looking for is "l"!

After looking to see which memory address was set to 1 in sub_10009aa0 (it sets 0x10019460 to 1), I kept going through this process until I had walked through and made a table like this:

"1" address           subroutine                (ascii)

0x10017000          sub_10009aa0()                 l
0x10019460          sub_10009440()                 0
0x10019464          sub_10009990()                 g   
0x10019468          sub_10009990()                 g
0x1001946c          sub_10009a30()                 i
0x10019470          sub_10009b10()                 n
0x10019474          sub_10009990()                 g
0x10019478          sub_10009880()                 .
0x1001947c          sub_10009b60()                 U
0x10019480          sub_10009cd0()                 r
0x10019484          sub_10009d80()                 .

...etc...

Eventually, these characters spell out an email address--

l0gging.Ur.5tr0ke5@flare-on.com

We're done!


No comments:

Post a Comment