Skip to content

Latest commit

 

History

History
195 lines (114 loc) · 10 KB

Brbbot.md

File metadata and controls

195 lines (114 loc) · 10 KB

Brbbot

Malware Name File Type SHA256
Brbbot x64 exe F9227a44ea25a7ee8148e2d0532b14bb640f6dc52cb5b22a9f4fa7fa037417fa

Analysis process

First thing first, I started Procmon in order to get an idea of the malware main activities:

Two interesting operations that were seen, were dropping a config file and self-copying to \AppData\Roaming\ path. Opening the file in Pestudio we see that the file is packed using UPX:

Trying to unpack it using UPX will throw an error:

3

This suspicious error indicates that the malware packed using UPX but then modified in such a way that the tool would not be able to unpack it back again. If we pay attention closely to the image above, we can see that one section renamed to NPX0 (it should be UPX0). Therefore, there are two ways to unpack the malware:

  • Modify the PE file on disk by renaming the section NPX0 → UPX0, then try to unpack using UPX tool again (at the end of this WriteUp)
  • Unpack it in memory using a debugger.

It is Important to note that the first method suitable just for very specific cases, most malware would be packed with custom & unknown packers, therefore, unpacking them must occur in memory.

So, dropping the sample to x64dbg...

A known trick (suitable for packers that work like UPX) to find OEP (Original Entry Point) is to locate a jmp opcode followed by a bunch of NULL bytes, that jumps high and far to a distant location. This is the point where the code decrypted / decompressed / decoded itself in memory and now jumping to the real deal – OEP.

So found it and break on it:

4

Single-step and we landed at OEP:

5

Now we are at the entry point of the real malware business, and all the imports should be resolved by the UPX loader in that point, so we use the built-in tool Scylla to rebuild the IAT and dump the unpacked malware to disk:

6

We can see now new suspicious libraries and imports that were not there on the packed file.

Observing the strings of the dumped file reveals some gems:

7

  • There is a malware config file named brbconfig.tmp (that we already saw under procmon).
  • Autorun key for persistense
  • User-agent that indicated on a http request

Looking at the resources:

8

We can see a "CONFIG" resource, saving to disk:

9

eeergg! probably encrypted...

Sooo.. moving back again to debugging:

10

There is a call to IsDebuggerPresent, not quite sure if this is an anti-debugging attempt (if it is, it's really poor one) or part of the compiler nonsense, so anyway we'll use ScyllaHide:

11

Spraying some BP's on some interesting API calls:

12

First BP we encountered is CryptDecrypt:

13

This API call is used to decrypt blob of encrypted data (in conjuction with some more API calls from the CryptXXXX family). Malware often use this call to decrypt a payload, a config, or a dropped file.

As we can learn from MSDN the fifth argument (the grey one in the stack view) points to the blob of the encrypted data (in the memory dump view).

So, single-stepping over that call should decrypt that blob:

15

Vwallaaa !! this is the clear config :)

Config content:

"uri=ads.php;exec=cexe;file=elif;conf=fnoc;exit=tixe;encode=5b;sleep=30000"

  • uri - the uri for the panel file on the c2
  • exec, file, conf, exit - maybe bot commands?!
  • encode - single byte key that will use us later on
  • sleep - sleep amount for some point

Keep debugging:

16

Malware is trying to call home :)

The stack arguments for InternetConnectA:

17

The MSDN for InternetConnectA:

Second argument on the stack is our nice c2 address:

brb.3dtuts.by

The content that sent to the c2 was found nearby in memory using Process Hacker:

19

The malware exfiltrating the internal ip address, hostname and some encoded data.

Playing a little bit around with the encoded data and with the single byte key that retrieved before, brought me to write a little python script to Hexdump the decoded data (the receipt is: unhex the data --> xor with the single byte key):

import operator

def hexdump(src, length=16, sep='.'):
    FILTER = ''.join([(len(repr(chr(x))) == 3) and chr(x) or sep for x in range(256)])
    lines = []
    for c in range(0, len(src), length):
        chars = src[c: c + length]
        hex_ = ' '.join(['{:02x}'.format(x) for x in chars])
        if len(hex_) > 24:
            hex_ = '{} {}'.format(hex_[:24], hex_[24:])
        printable = ''.join(['{}'.format((x <= 127 and FILTER[x]) or sep) for x in chars])
        lines.append('{0:08x}  {1:{2}s} |{3:{4}s}|'.format(c, hex_, length * 3, printable, length))
    return '\n'.join(lines)


def decoder(hex_string, key, op):
    ops = {"xor": operator.xor, "and": operator.and_, "or": operator.or_}
    if op not in ops:
        return None
    else:
        byte_array = bytearray.fromhex(hex_string)
        byte_array_result = []
        for byte in byte_array:
            byte_array_result.append(ops[op](byte, key))
        return hexdump(byte_array_result)


def main():
    text = "123f373e600822282f3e3660093e3c32282f29226028362828753e233e603828292828753e233e602c32353235322f753e233e603828292828753e233e602c323537343c3435753e233e60283e292d32383e28753e233e6037283a2828753e233e60282d383334282f753e233e603d34352f3f292d3334282f753e233e603d34352f3f292d3334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e603f2c36753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e600d193423083e292d32383e753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60163e363429227b1834362b293e282832343560282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60282b343437282d753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60292e3922753e233e60282d383334282f753e233e602c373628753e233e601628162b1e353c753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e6028323334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e602f3a28303334282f2c753e233e60282d383334282f753e233e60382f3d363435753e233e60282d383334282f753e233e603e232b3734293e29753e233e60282d383334282f753e233e6008333e37371e232b3e29323e35383e1334282f753e233e60282d383334282f753e233e60083e3a2938330e12753e233e60092e352f32363e192934303e29753e233e60092e352f32363e192934303e29753e233e60282d383334282f753e233e60083e3a29383312353f3e233e29753e233e601a2b2b3732383a2f3234351d293a363e1334282f753e233e60163238293428343d2f1e3f3c3e753e233e60282d383334282f753e233e603929342c283e2904392934303e29753e233e60282d383334282f753e233e6002342e290b3334353e753e233e600830222b3e193a38303c29342e353f1334282f753e233e600c32353f342c28750c1a090b7511120f083e292d32383e753e233e600830222b3e1a2b2b753e233e60092e352f32363e192934303e29753e233e60163238293428343d2f1e3f3c3e180b753e233e60163238293428343d2f1e3f3c3e0813753e233e60173438301a2b2b753e233e60092e352f32363e192934303e29753e233e60092e352f32363e192934303e29753e233e60282d383334282f753e233e60092e352f32363e192934303e29753e233e60092e352f32363e192934303e29753e233e6028363a292f2838293e3e35753e233e60083e382e29322f22133e3a372f330822282f293a22753e233e60083e382e29322f22133e3a372f33083e292d32383e753e233e600d1934230f293a22753e233e6014353e1f29322d3e753e233e600c3235082f34293e751a2b2b753e233e60092e352f32363e192934303e29753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60083c2936192934303e29753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e600c32353f342c2812352f3e29353a37751834362b34283a39373e08333e3737751e232b3e29323e35383e28750f3e232f12352b2e2f7512352b2e2f1a2b2b753e233e603f37373334282f753e233e600822282f3e36083e2f2f32353c28192934303e29753e233e60282d383334282f753e233e60282d383334282f753e233e60282d383334282f753e233e600822282f3e36083e2f2f32353c28753e233e60282d383334282f753e233e60236d6f3f393c753e233e600835322b2b32353c0f343437753e233e60282d383334282f753e233e6039293939342f753e233e60083e3a2938330b29342f343834371334282f753e233e60083e3a2938331d32372f3e291334282f753e233e60393a38303c29342e353f0f3a28301334282f753e233e60092e352f32363e192934303e29753e233e60282d383334282f753e233e600c36320b292d081e753e233e6038363f753e233e603834353334282f753e233e60292e3922753e233e"
    key = 0x5b
    print(decoder(text, key, "xor"))

main()

The malware send the process list to the c2.

Rest of the malware functionality comes down to this:

Read a file from the c2:

21

Create a new process:

22

Both implies that the infection isn't over and the party continues with the next stage :)

Bonus – unpacking on disk

  • Locate renamed section with a hex editor, and rename it to original:

b1 b2

  • Save:

b3

  • Unpack using UPX tool:

b4