Title: quick reversing of Wirenet
Date: 2012-09-24 18:59

Thanks to [r00tBSD](http://www.r00ted.com), I've now got a access to the database of [malware.lu]( https://malwares.lu).
To celebrate this, I've try to reverse a dead-simple sample: the infamous [BackDoor.Wirenet.1]( https://malware.lu/sample/search.html?hash=9a0e765eecc5433af3dc726206ecc56e)!

# Preliminary analysis 

```bash
$ file 9a0e765eecc5433af3dc726206ecc56e
9a0e765eecc5433af3dc726206ecc56e: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), BuildID[sha1]=0xeb836a1de23ce2cbe86a30064bc20e9f2c8b024c, stripped
```

Ho, shared libs, nice.

The `string` command give us a lot of informations :

- The binary doesn't seems to be packed!?
- AES and RC4 for crypto
- Password stealing for Mozilla Firefox/Thunderbird/Seamonkey, Pidgin, Opera and Chromium?
- Xorg stuffs, likely screenshots
- Keylogger
- A remote shell using bash is available, or sh if not.
- Autostart/persistence
- SOCKS4/5 proxy
- No IP/login/filename/... in cleartext

```bash
$ strings 9a0e765eecc5433af3dc726206ecc56e | grep cp
```

This command give a quick overview of wirenet's capabilities.

# Functionalities overview
A quick look into the disassembly code tells us that the malware is also able to control the mouse, download/upload/execute/rename/move files,
update/uninstall itself, list/kill processes, get a windows list, change windows names, ...

# Analysis of interesting functions

## DecryptSettings
Let's go for dead-simple crypto !

```nasm
.text:08052DEC
.text:08052DEC                 public DecryptSettings
.text:08052DEC DecryptSettings proc near               ; CODE XREF: ReadSettings+Ap
.text:08052DEC
.text:08052DEC var_114         = byte ptr -114h
.text:08052DEC
.text:08052DEC                 push    ebx
.text:08052DED                 sub     esp, 11Ch
.text:08052DF3                 push    10h
.text:08052DF5                 push    offset BuilderEncryptionKey
.text:08052DFA                 lea     ebx, [esp+128h+var_114]
.text:08052DFE                 push    ebx
.text:08052DFF                 call    RC4Setup
.text:08052E04                 add     esp, 0Ch
.text:08052E07                 push    0FFh
.text:08052E0C                 push    offset ConnectionString
.text:08052E11                 push    ebx
.text:08052E12                 call    RC4Crypt
.text:08052E17                 add     esp, 0Ch
.text:08052E1A                 push    0FFh
.text:08052E1F                 push    offset ProxyString
.text:08052E24                 push    ebx
.text:08052E25                 call    RC4Crypt
.text:08052E2A                 add     esp, 0Ch
.text:08052E2D                 push    20h
.text:08052E2F                 push    offset Password
.text:08052E34                 push    ebx
[...]
.text:08052EBB                 call    RC4Crypt
.text:08052EC0                 add     esp, 128h
.text:08052EC6                 pop     ebx
.text:08052EC7                 retn
.text:08052EC7 Decry
```

It seems to decrypt settings strings with RC4, and the key is located at `BuilderEncryptionKey`.
Let's decrypt all this mess with some pythonic magic !

```python
import sys
from Crypto.Cipher import ARC4

tab = [
		{'name':'ConnectionString', 'size':256, 'offset':0xf610},
		{'name':'ProxyString', 'size':256, 'offset':0xf510},
		{'name':'Password', 'size':32, 'offset':0xf4ec},
		{'name':'HostId', 'size':16, 'offset':0xf4c4},
		{'name':'MutexName', 'size':8, 'offset':0xf4b8},
		{'name':'InstallPath', 'size':128, 'offset':0xf434},
		{'name':'SetupKeyName1', 'size':16, 'offset':0xf420},
		{'name':'SetupKeyName2', 'size':38, 'offset':0xf3f8},
		{'name':'KeyloggerFileName', 'size':128, 'offset':0xf374},
		{'name':'BoolSettingByte', 'size':4, 'offset':0xf370},
		{'name':'ConnectionType', 'size':4, 'offset':0xf36c},
		]

if len(sys.argv) != 2:
	print('Usage: %s wirenet_sample') % sys.argv[0]
	sys.exit()

fd = open(sys.argv[1], 'r')

#the RC4 key is at offset 0xf4d8
fd.seek(0xf4d8)
key = fd.read(16)

for s in tab:
	rc4 = ARC4.new(key)
	fd.seek(s['offset'])
	data = fd.read(s['size'])
	decyphered = rc4.decrypt(data)
	clear_text = decyphered.split('\x00')[0]
	print('%s: %s') % (s['name'], clear_text)
```

This prints :

```bash
ConnectionString: 212.7.208.65:4141;
ProxyString: -
Password: sm0k4s523syst3m523 #AES key
HostId: LINUX
MutexName: vJEewiWD
InstallPath: %home%/WIFIADAPT
SetupKeyName1: WIFIADAPTER  #Key used for autostart
SetupKeyName2: -
KeyloggerFileName: %Home%\.m8d.dat
BoolSettingByte: 237I
ConnectionType: 001
```
## InstallHost

First, a mutex named `vJEewiWD` is created, and depending of options, multiples things can happens:

- The malware can be installed in "InstallPath", which is `%home%/WIFIADAPT`
- The malware can be automatically started on login, by creating a file named `%HOME%/.config/autostart/WIFIADAPTER.desktop`.
- The malware can be also be automatically started by a line into the `%HOME%/.xinitrc`.
- The malware can be run as a daemon, by forking itself
- The keylogger may be immediately started in a separated thread.

## Password stealer
Nothing hardcore, nor noticeably cleaver here. I don't get why the author didn't use the sqlite library instead of hackish crap.

## GetMozillaProductPasswords

This function recovers logins/passwords from Thunderbird, Firefox and Seamonkey.
The procedure is common for the 3 products:

1. Get profile path by looking into `%HOME%/[.mozilla[/firefox|/seamonkey]|.thunderbird]/profiles.ini` for the *Path* variable
2. Open the `signons.sqlite` which contains logins/passwords
3. Execute `"select *  from moz_logins"` to get every passwords using Mozilla's own functions:
	1. PK11_GetInternalKeySlot
    2. PK11_Authenticate
    3. NSSBase64_DecodeBuffer
    4. PK11SDR_Decrypt
    5. PK11_FreeSlot
    6. NSS_Shutdown<

### GetGoogleChromePasswords
Data are either in `%HOME%/.config/google-chrome/Default/Login Data` for Google Chrome, or in `%HOME%/.config/chromium/Default/Login Data` for Chromium.
This time, no sql request : the sqlite table is decoded as it.

### GetOperaWand
This time, the whole file (`%HOME%/.opera/wand.dat`) containing logins/passwords is sent to the C&C, not a dumped list.
Maybe the author was to lazy to write a [decrypted]({static}/files/reverse/unwand.cpp)?

### GetPidginPasswords
Some XML parsing of `%HOME%/.purple/accounts.xml`.

## Keylogging
On GNU/Linux, deploying a keylogger doesn't require a root account.
The routine used in this malware is quite common:

1. `XOpenDisplay()` to get the Display
2. `XQueryExtension([..]XInputExtension[..])` to check if the XInputExtension is present
3. `XListInputDevices()` to get input devices, looking for a "AT" or a "System Keyboard" one.
4. `XOpenDevice()` to handle the device
5. `XSelectExtensionEvent()` to get interesting events
6. An infinite loop calling `XNextEvent()` to get events. If an event is found, it's logged into `%HOME%\.m8d.dat` using the (ugly) `LogKey(XKeyEvent *, Display *)` function.

## CaptureScreen
This function does the following:

1. Get an XImage using XGetGeometry then XGetImage.
2. Convert the XImage to BMP.
3. Convert the BMP to JPEG.

## Misc. functions

- cpGetComputerName: using *gethostname()*
- cpGetOSVersion: looking into */etc/lsb-release*
- cpGetUsername: using *getenv("USER")*
- ChangeWindowTitle: using *XChangeProperty()*

# Communication with the C&C 
Nothing funky here. The C&C's IP is 212.7.208.65:4141, everything is transmitted using AES, with "sm0k4s523syst3m523" as key. The authentication packet is "RGI28DQ30QB8Q1F7" (in clear in the binary).

A whois tells us that this is a Dediserv server (PL) routed via LeaseWeb (NL).
Let's see what nmap's got for us:

```bash
# nmap [..] 212.7.208.65
22/tcp  filtered ssh
80/tcp  filtered http
111/tcp open     rpcbind
|  rpcinfo:
|  100000  2,3,4    111/udp  rpcbind
|  100024  1      41019/udp  status
|  100000  2,3,4    111/tcp  rpcbind
|_ 100024  1      28564/tcp  status
135/tcp filtered msrpc
139/tcp filtered netbios-ssn
445/tcp filtered microsoft-ds
No exact OS matches for host
```


# Conclusion
Nothing groundbreaking, but since this was my first malware reversing under GNU/Linux, I had a lot of fun.
