LCPP – a Lua C PreProcessor

Written by will on June 17, 2013 Categories: C, Lua, LuaJIT

We released and published LCPP under opensource License (MIT). LCPP`s main focus is to enable LuaJIT ffi C pre-processing, but it can be used as a standard cpp with Lua5.1. Its basically a more or less complete cpp implementation as a single Lua module without depencies.

On GitHub: https://github.com/willsteel/lcpp
Project page: http://lcpp.schmoock.net/

Examples

-- load lcpp (ffi and tests turned on per default)
local lcpp = require("lcpp")

-- just use LuaJIT ffi and lcpp together
ffi.cdef('#include "your_header.h"')

-- or compile some code by hand
local result = lcpp.compile("...")
local out = lcpp.compile([[
    #define MAXPATH 260
    typedef struct somestruct_t {
        void*          base;
        size_t         size;
        wchar_t        path[MAXPATH];
    } t_exe;
]])

It supports most cpp directives as well as functional macros and nested blocks etc… however some string operations like stringify operator “#” or string concatenation are still missing (yet). For a pure Lua solution it has remarkable performance, since we use it to compile ollydbg plugin header 4k loc during runtime in about 100ms.

will

(more…)

No Comments

mmBBQ release 3.0.2

Written by will on April 14, 2013 Categories: assembler, reverse engineering, windows Tags: 

We finally found some time to do a proper release of mmBBQ!

Much new stuff and some old bugs fixed in:
http://duschkumpane.org/mmbbq/releases/mmbbq_3.0.2.zip

* hellgate global update
* hellgate radar hack
* memory leak fixed
* improved exception handling
* increased performance of low level handlers

No Comments

Get OllyDbg to work with ALSR offsets

Written by defragger on January 11, 2013 Categories: assembler, reverse engineering, windows

Heya, sometimes you have to reverse an ASLR “protected” process with ollyDbg. Unfortunately, Olly does ont have an JUMP-TO (Ctrl+g) command for relative base offsets. So i implemented one myself using mmBBQ.

local function odbg_cexpression_offset(context)
    local addr = context.arg32(1, "wchar_t*");
    local wstring = wstr(addr);
    if string.starts(wstring, "+") then
        local mod = odbg.getMainModule();
        string_addr  = string.format("0x%X", (wstring+mod.base));
        dbg.writeMemory(addr, char2wchar(string_addr));
    end
end


codecave.inject("odbg_cexpression_offset", getProcAddress(0, "Cexpression"), odbg_cexpression_offset, codecave.INTERCEPT_PRE);

It simply injects a codecave at the function Cexpression. If the function is called (ctrl+g -> Follow expression) it searches for a + at the first Position of the string and adds BaseOfCode+ImageBase to the value after the +. I will add a ollyDbg package to mmbbq in a later revision.

greetz defragger

EDIT:
i changed the code a bit, we dont need to allocate a buffer for our new string. olly made enough place on stack wchar_t[256] for that expression string so we simply write into the stack :)

 

4 Comments

Locating binary modifications using vimdiff

Written by defragger on August 17, 2012 Categories: assembler, linux, reverse engineering, vim, windows Tags: , , , , , , ,

Introduction

Sometimes its necessary to locate changes within a running binary or module. This can be for the reasons of a malware modifying your code, or you want to understand how a certain bot/hack/crack is working with your process. In both cases this information can be very valuable to you.

What you need

  • A program of your choice (Where your are able to attach)
  • Something that hooks into it (Maybe a Bot or some kind of malware. Its up to you)
  • The debugger OllyDbg 1.10
  • The text editor Vim. (vimdiff is included)

Step by step

  1. First load your program into OllyDbg and then in the code section “right click” -> “Copy” -> “Select All”. After that “right click” -> “Copy” -> “To file”. Note: won’t work in OllyDbg2
  2. Now we start the program and inject/malware/hack into it and do the same selectAll/Copy procedure again but choose another filename at the end.
  3. And after that we run: $> vimdiff normal.txt hooked.txt

The epic result


… now its very easy to locate code that is accessing / modifying this module. Those are the fat red marks in the HEX section of the ASM dump. So we can analyze it pretty fast, simply by jumping to the next difference.

Greetz,
defragger

3 Comments

Building an MMORPG Bot from scratch – Part2

Written by defragger on August 16, 2012 Categories: assembler, reverse engineering, windows Tags: , , ,

Part2 – Networking functions

In this Part2 of the tutorial series we will try to find suitable points to extract the network packets while they are being send or received by the client. I think it is a good step into reversing an unknown program to check the I/O APIs used by it.

The chapters

In this Chapter

  • Locate packet reading functions
  • Understanding the packet structure
  • Locate packet sending function

Requirements

  • Silkroad Online
  • A decent debugger: OllyDbg 2.X
  • A codecaving and injection framework: mmBBQ 3.X
  • An editor of your choice (mine is Vim ;) )

Packet reading:

Normally the functions that will be called if you want to read or send network packets is WSARecv(..) for receiving new packets and WSASend(...). Of course this applies to MS Windows APIs. So we are going to set breakpoints there. To do so we load our modified executable (described in Part1) and run it. Then we log into the game to make sure all dynamic modules are loaded before we proceed. Now we can search for all inter-modul calls: (right click -> Search for -> “All intermodular calls”). This is a huge list, but you can now just type the string youre searching for, in our case “WSAR” should be enough to find the right call:
null

Now set a normal software breakpoint (INT3) at the desired position (F2) or double click in the hex presentation of the call to “WSARecv”.
The next steps are the secret when reverse engineering. Just ask yourself the following questions:

  1. What are we searching?
  2. How does the searched position could look like?
  3. What should happen before and after this secret location?
  4. What do we want to do at this location?
  5. Especially what event could bring us to this position?

Actually we are searching for the packet read function. It should get as parameter the complete packet (maybe separate the packet id) We would like to hook this position to get more information what packet could define which event. The entry point in our search for this function is WSARecv(...) (or any other network receive function from your operating system API).

With this vague description of our searched location we start at the breakpoint of the call to WSARecv(...). So the next packet read will interrupt the program in OllyDbg. Before we set the breakpoint at this position we should think about a good event or moment to receive a usable breakpoint hit (and that way a cool packet LPWSABUF). For this matter I have chosen the moment when you selecte a character. Just before you click start, set the breakpoint. As the breakpoint hits, we see the following stack:
null

A small look into the Msdn will bring us knowledge about the parameters seen here. The most interesting attribute is

LPWSABUF lpBuffers

defined here: Msdn (LPWSABUF)

So when we follow the pointer (by left clicking on address -> Right click -> “Follow DWORD in Dump”) to this data structure we will see this:
null
The second member of this struct contains a pointer to the buffer that will be filled with the received data.

One Step over (F8) later we can see how the packet was filled by WSARecv:
null

At this point we have several options to go on:
- We set a Memory Read Breakpoint within the received data to see what code reads this information. To set a Memory Breakpoint, mark the memory you want to BP and press Shift+F3 (or Right click -> Breakpoint -> Memory). Set Read access and click ok. Note: Its not wise to set the breakpoint directly in the first bytes of the buffer, because we can assume that the start of a packet will contain mostly the id and the length of it. Good, now you are able to run (F9) again so the process will continue until somebody reads the breakpointed addresses. This will lead us to:
null

The REP MOVS instruction copies ECX DWORD (32Bit) from ESI to EDI. Command help can always be opend by: Shift-F1. Now step over this rep movs with (F8) and select EDI (right click -> Follow in Dump). We set a memory read breakpoint in this area and run run. Now we reach again the WSARecv call (Step over and eax tells us there was nothing to receive 0xFFFFFFFF == -1). Another run bring us to the next rep mov. Stepping to the end of this function

null

shows us that the new filled buffer is the return value here (contained in EAX) Another few steps in the calling function ends

null

As return value we get the received packet:
null

 typedef struct sro_packet_t{
    /* 0x00 */ void** functions;
    /* 0x04 */ uint32_t bytes_read;
    /* 0x08 */ uint32_t len;
    /* 0x0C */ uint32_t unknown1;
    /* 0x10 */ unsigned char* buffer;
    /* 0x14 */ unsigned char* buffer2;
    /* 0x18 */ uint16_t packet_id;
    /* 0x1A */ uint16_t unknown2;
}sro_packet_t; 

At this point a little bit of reversers intuition is needed, to show the way I set memory breakpoints to anything except the void** functions part. Now play and we reach this function:
null

If we step a bit forward there is a call to 0xCD9540. The functions first argument is the address of the packet_t struct. We can assume what part of this data can be the packet id. In the screen above the packet id is 0x34A5. So right click in the text section -> Search for -> All constants, enter the value 0x34A5 and press OK:
null

We follow the second result here and reach a really interesting function :)
null

This function contains a bunch of calls that create a callback for a specific packet_id. The first MOV is the packet id and the second is the function that will be called if that specific packet arrives. In our case we copy the function address for 0x34A5 (0x943F40) and press Ctrl+g to jump to that address in the code. We set a normal breakpoint at this address and restart the application. The breakpoint then hits after pressing start. And we can follow up the stack until we see a function that matches our needs. In our actual case there are 4 RETURNs before 0xCD9540.

So next step is to hook our new discovered function first thing here is to define the packet_t struct in lua:

ffi.cdef[[
    typedef struct sro_packet_t{
        /* 0x00 */ void** functions;
        /* 0x04 */ uint32_t bytes_read;
        /* 0x08 */ uint32_t len;
        /* 0x0C */ uint32_t unknown1;
        /* 0x10 */ unsigned char* buffer;
        /* 0x14 */ unsigned char* buffer2;
        /* 0x18 */ uint16_t packet_id;
        /* 0x1A */ uint16_t unknown2;
    }sro_packet_t;
]]

Next we have to define the function that will be called before 0xCD9540 is called:

local function hook_packet_read(context)
    local packet = cast("sro_packet_t*", context.arg32(1));
    local buf = ffi.string(packet.buffer, packet.len);
    print("[READ]: "..packet.packet_id);
end

Finally we set a codecave at the top of function 0xCD9540:

 codecave.inject("packet_read", 0xCD9540, hook_packet_read);

When these three blocks of Lua code are inserted i.e. at the end of config.lua, mmBBQ will print out the read packet codes as they pass by. We already added a lot of packetfilter stuff in the file: sro_net.lua. To see the full lua sourcecode of that just download the mmbbq SDK from here.

Packet Sending functions

To finish our packet journey we still need to find a suitable function for packet send. The start will be the same as the read part except that we breakpoint WSASend this time and follow the control flow up. This time its a bit more easy cause of the stack.

null

We will select the last return addr here 0x8CE578 (right click -> Follow in Disassembler) Now we set a breakpoint at the top of the reached function and run run. If we are fast enough another time the breakpoint hits, otherwise we receive a disconnect and we have to reload the binary again. The breakpoint hits and we follow the return address in the stack to the calling function. If we breakpoint the top of this function again and the breakpoint hits we will see that the first argument is a pointer on the stack. We follow this address in dump and we see a similar
structure we already know from packet_read 0x8CE980 is the function address.

local function hook_packet_send(context)
    local packet = cast("sro_packet_t*", context.arg32(1));
    local buf = ffi.string(packet.buffer, packet.len);
    print("[SEND]: "..packet.packet_id);
end
codecave.inject("packet_send", 0x8CE980, hook_packet_send);

I hope my writings are informative and that you can adopt it for your the work. Feel free to contact me on suggestions or questions: #duschkumpane at freenode irc

Greetz,
defragger

18 Comments

Extracting hidden base64 from a binary

Written by defragger on  Categories: assembler, linux, reverse engineering, windows, x64 Tags: , , , , , , ,

The task:

Today i want to show how to easy extract base64 encoded strings from a binary using a simple shell command. This is particularly important if you need to quick check what a certain malware is about to do. The method can be adopted to locate other encodings as well. As example i have chosen EagleX64.sys (thats the 64Bit driver of HackShield) I know thats not the best regex to find base64 parts but it should work for this example :)

for i in `grep -aEo "[A-Za-z0-9=+/]{10,}" EagleX64.sys`; do \
    echo $i | base64 -di; echo " "; \
done

And here the result:

ntoskrnl.exe
ntkrnlpa.exe
ntkrnlmp.exe
ntkrpamp.exe
CSRSS.EXE
\Driver\HidUsb
\Driver\HidBth
\Driver\wacomvhid
\Driver\wacomvkhid
\Driver\SaiMini
\Driver\WmVirHid
\Driver\LHidUsb
\Driver\LHidEqd
\Driver\LHidFilt
\Driver\i8042prt
PsSetCreateProcessNotifyRoutine
IoAllocateWorkItem
IoQueueWorkItem
IoFreeWorkItem
PsGetCurrentProcessId
PsLookupProcessByProcessId
ZwQueryInformationProcess
ObReferenceObjectByHandle
ObDereferenceObject
RtlInitAnsiString
RtlAnsiStringToUnicodeString
RtlFreeUnicodeString
RtlEqualUnicodeString
PsGetCurrentThreadId
KeQueryActiveProcessors
KeWaitForSingleObject
KeInitializeEvent
PsCreateSystemThread
ZwSetInformationThread
KeSetEvent
KeInitializeTimerEx
KeSetTimerEx
KeCancelTimer
KeInitializeDpc
KeWaitForMultipleObjects
PsTerminateSystemThread
ZwClose
KdDisableDebugger
KdDebuggerEnabled
ObOpenObjectByPointer
ZwTerminateProcess
HalQueryRealTimeClock
ObRegisterCallbacks
ObUnRegisterCallbacks
\Driver\kbdclass
\Driver\mouclass
SVCHOST.EXE
LSASS.EXE
SERVICES.EXE
WINLOGON.EXE
EXPLORER.EXE
IEXPLORE.EXE
SPOOLSV.EXE
TCSERVER.EXE
IMJPCMNT.EXE
NOD32KRN.EXE
UPSHIFTMSGR.EXE
NSVCAPPFLT.EXE
NMSERVICE.EXE
SETPOINT.EXE
HGSCRAPEDITORHELPER.EXE
TASKMGR.EXE
NGM.EXE
AUDIODG.EXE
DEKARON.EXE
NMCOSRV.EXE
IPOINT.EXE
VAIOCAMERACAPTUREUTILITY.EXE
GAMEMON.DES
GOM.EXE
EKRN.EXE
RAGII.EXE
CSTRIKE-ONLINE.EXE
DK2.EXE
WMIPRVSE.EXE
DWM.EXE
JOYTOKEY.EXE
JOYTOKEYKR.EXE
JOYTOKEYHIDE.EXE
Joy2Key.exe
ITYPE.EXE
ACS.EXE
LGDCORE.EXE
fssm32.exe
xsync.exe
WmiApSrv.exe
avp.exe
IAANTmon.exe  
WerFault.exe
…§$²ž•

Note: This is just a quick check, the malware can trick you by hiding the “real” stuff in way harder to detect. But in this case it works perfectly.

Greetz defragger

1 Comment

decrypting and analyzing proprietary protocols

Written by will on August 10, 2012 Categories: assembler, reverse engineering, windows Tags: , , ,
… An exemplary walkthrough in 15 minutes

Introduction

Many commercial voice and messenger applications are known to have an encrypted network protocol. I will show you how to decode and analyze proprietary network protocols in just a few steps. The method i’ll show you will work for many programs. Teamspeak3 is taken exemplarily. You should be able to adopt and apply the techniques described here to whatever program you like. Note: some of the described aspects will also work on the otherwise undebuggable Skype client binary :]

Background

Why are many proprietary protocols encrypted? If I had to guess it’s because of two reasons:

  1. The programmers think its more secure, because security issues can’t be detected so easily.
  2. To reduce the number of compatible opensource software, by saying its forbidden to reverse engineer their encrypted protocols.

The first one is a common mistake. I call it security by obscurity. Encrypting an interface (the network protocol is an interface) only increases the chance that evil guys write exploits to use them and keep them for themselves. The second one is not applicable and overgrown by European law.

So why do we decode them?

  • for the purpose of interoprability: opensource clients and other platforms
  • point out security issues
  • to protect your privacy. You can’t know what data is transferred until you checked it
  • for fun and profit

What you need is:

  • a recent mmBBQ version (3.0.1 or upwards)
  • a text editor to add the Lua codes to your config.lua file
  • the official Teamspeak3 client binary (i.e. 3.0.8.1)

STEP 1 – Reading RAW network data

For reading raw un-decrypted network data, we just hook the used windows network API: WSASendTo(…) and WSAReadFrom(…). Note other win32 apps maybe using the WSASend(…) and WSARecv(…) variants or even other methods to read data. In order to hook the network functions just need some lines of code at the bottom of your config.lua:

-- MSDN: int WSARecvFrom( __in     SOCKET s, __inout  LPWSABUF lpBuffers, __in     DWORD dwBufferCount, __out    LPDWORD lpNumberOfBytesRecvd, ... );
local function wsa_recv(context)
    local buflen = context.arg32(2, "uint32_t**")[0];
    local buf = context.arg32(2, "char**")[1];
    local recv = context.arg32(4, "uint32_t*")[0];
    if recv > 0 then
        printf("[RECV] 0x%X", recv);
        hexdump(buf, recv);
    end
end
codecave.inject(nil, getProcAddress("ws2_32", "WSARecvFrom"), wsa_recv, codecave.INTERCEPT_RETURN)

The `codecave.inject(…)` does the actual hooking. The hook refers to the functions declared before: `wsa_send` and `wsa_recv`. The hooks just parse and dump the stack arguments from the function. The signature can be taken from the official MSDN docs. If you are known to LuaJIT fii API theres no magic in it, if not I recommend reading the LuaJIT ffi Doc and maybe our codecaving doc.

The applied hooks will result in this console output:
console output
We can see the raw data as it passes by, just as if we are using wireshark. By just estimating the number and distribution of zero bytes 0×00 in the bigger transmissions we can assume that the data is still encrypted. The repetitive transmission seem to be the keepalive or timesync. those look unencrpyted, because we can see incrementing hex numbers and a similar data layout as prefix.

STEP 2 – Locating the decryption routines

Most applications use symmetric stream encryption (http://en.wikipedia.org/wiki/Symmetric-key_algorithm). They work either by pseudo number generators or by predefined shuffle arrays. This is no rocket science. Its well proven, less CPU intense and included in many stream encryption libraries used by those applications. In order to detect the decrpytion routines in the binary we can exploit a common nature of those algorithms: They work directly on the input data, and are executed as the first access to a received network buffer.

With that knowledge in mind, we just add a memory breakpoint to a buffer when it was received (at the end of hook function wsa_recv). When it fires we know the Instruction pointer (EIP) where the buffer is going to be modified next. Note: we check the length of received buffer, because the “small” keepalives don’t seem to be encrypted.

...
    if recv > 0xF then
        dbg.mbpAdd(buf + 0xF, function(bp) bp.print(); bp.del(); end, 1, dbg.MBP_WRITE);
    end

This automatically installs a one-shot memory breakpoint when data is received from network. On trigger it will execute two things: `dbg.print()` and `bp.del()`. The `dbg.print()` will print out the cuurent context and disassembly when the memory breakpoint fires. The `bp.del()` will delete the memory breakpoint again, so it behaves in a one shot manner… As easy as pie, isn’t it?

Now, when connected we attach our code again and click around the channels to trigger a network read that is larger than the small keepalives. Eventually we will see the decoding function context print that we just installed automatically … :]
Catched Context of decryption routine

Yay, now we see theres a little loop that is writing to our buffer… it jumps back to 0x009037D0 on a certain loop condition. lets see the whole loop. just type dbg.asm(0x009037D0, 7) into the Lua console and we will get:

0x009037D0              8b3c02                  mov edi, [edx+eax]
0x009037D3              33bc0e94000000          xor edi, [esi+ecx+0x94]
0x009037DA              83c104                  add ecx, 0x4
0x009037DD              8938                    mov [eax], edi
0x009037DF              83c004                  add eax, 0x4
0x009037E2              3b4e04                  cmp ecx, [esi+0x4]
0x009037E5              7ce9                    jl 0x9037d0

The XOR operation at 0x009037D3 is also a very good hint that this is part of a decryption/encryption routine. Pretty straight forward this little snippet does the following things:

  1. load the next DWORD to EDI (from the buffer pointer EDX)
  2. decode the data using XOR and a stream source object or class (ECX+0×94)
  3. increment the streamsource ECX by 0×4 (sizeof(DWORD))
  4. write out the decrypted data to the original buffer (we catched that instruction earlier)
  5. also increment output pointer EAX (used in the last instruction)
  6. compare abort condition and repeat until finished

Sure there is more to understand about the streamsource and maybe the initial key, but for the time being that’s it. Lets just try to get the data displayed decoded as it passes through…

STEP 3 – Dumping the decoded data

When we look closer at the previous Context print (last console screenshot) we notice a Code reference in the current Stack
 0x00903894 : CODE 0x00400000 ts3client_win32.exe+0x00503894(). Code references in the stack are most likely return addresses of function calls. Lets investigate that by installing a debug codecave: codecave.debug(0x00903894):
Untitled
… the decrypted stuff!! The following entry in the stack should be the buffer size (0×21). When we look at the previous match, we can see that this cave is also executed for encrypting things (the yellow mark in the screenshot).

Now we can make a suitable cave that dumps us any data: post-decrypted when received and pre-encryption when send. Lets reload our console so codecaves and BPs are cleared. Maybe you also want to remove the hexdumps and auto breakpoint thing set in Step1. To find the entrypoint into the crypt function we can query the “return address – 0×5″. In x86 assembler the returns address always points to the CALL+0×5 bytes, because thats the size of the call instruction itself. So we can examine the function call to the crypt function to get the entrypoint:
dbg.asm(0x00903894 - 0x5) -> call dword 0x903640.
What we did here is to determine the first instruction of the encryption/decryption function. This can also be done with OllyDbg by just looking there. The next versions of mmBBQ will eventually include more disassembly functions.

Now lets place a debug cave at there: codecave.debug(0x903640)
In the same way we detected the return address before we now see two calls to this address. The one we already knew for decrypting 0x00903894 and the call for encrypting data 0x0090F81B.

Okay, now we just make Lua codecaves there, one that is executed on return (decryption) and one that is executed on call (encryption). We can differ them by looking at the return address. The approach is the same in the hooking of WSARevcFrom in Step1.

local function decrpyt_hook(context)
    local ret = context.arg32(0, "uint32_t");
    if ret == 0x00903894 then
        printf("RECV_CRYPT: %s", str(context.arg32(2, "char*"), context.arg32(3, "int")));
    end
end
codecave.inject(nil, 0x903640, decrpyt_hook, codecave.INTERCEPT_RETURN)

local function encrypt_hook(context)
    local ret = context.arg32(0, "uint32_t");
    if ret == 0x0090F81B then
        printf("SEND_CRYPT: %s", str(context.arg32(2, "char*"), context.arg32(3, "int")));
    end
end
codecave.inject(nil, 0x903640, encrypt_hook, codecave.INTERCEPT_PRE)

Doing so will result in the fully decrypted control port protocol. So we are finished here. Funny thing is that ts3 uses an ASCII plain text protocol which is not very common. Maybe its easier to debug. I learned to design protocols by sending codes and compressed data with little overhead.

SEND_CRYPT: clientinitiv alpha=lk34sdLIASjdka== omega=LIJd5ldk2LJDjalK1UaF411oon\/V82tqmaM0p8dr6qKmQp9RiK+sCID7
W98OrGCKD+c8erzHWyAaASsxc3l2kkl\/TGxQbV3 ip=123.123.123.123
RECV_CRYPT: initivexpand alpha=lk34sdLIASjdka== beta=wp82a901Q05O8qg== omega=LIJd5ldk2LJDjalK1UaF411oon\/Afh\/GOSJLsAwdV
e\/BUbnFL0sYc49hSfCIDB\/37L0EZb0WaI2pC4FAd5gbvzgp2ZjsSrvnOSASMav
SEND_CRYPT: clientinit client_nickname=will client_version=3.0.8.1\s[Build:\s1343657352] client_platform=Windows client_
input_hardware=1 client_output_hardware=1 client_default_channel client_default_channel_password client_server_password=
fHzk+43klKq2SnfCS1B3r+HCakI= client_key_offset=291 client_nickname_phonetic client_default_token hwid=198b8902374b0973c1
8as097aft3,01h4m5cmpw8qytc83
RECV_CRYPT: initserver virtualserver_name=FooBarServer virtualserver_welcomemessage=Welcome\sto\sTeamSpeak,\sc
heck\s[URL]www.teamspeak.com[\/URL]\sfor\slatest\sinformation virtualserver_platform=Linux virtualserver_version=3.0.5\s
[Build:\s1335655378] virtualserver_maxclients=32 virtualserver_created=1337381436 virtualserver_codec_encryption_mode=0
virtualserver_hostmessage virtualserver_hostmessage_mode=0 virtualserver_default_server_group=8 virtualserver_default_ch
annel_group=8 virtual
RECV_CRYPT: server_hostbanner_url virtualserver_hostbanner_gfx_url virtualserver_hostbanner_gfx_interval=0 virtualserver
_priority_speaker_dimm_modificator=-18.0000 virtualserver_id=1 virtualserver_hostbutton_tooltip virtualserver_hostbutton
_url virtualserver_hostbutton_gfx_url virtualserver_name_phonetic virtualserver_icon_id=0 virtualserver_ip virtualserver
_ask_for_privilegekey=0 virtualserver_hostbanner_mode=0 acn=will aclid=1 pv=6 lt=0 client_talk_power=75 client_needed_se
rverquery_view_power=
RECV_CRYPT: channellist cid=4 cpid=0 channel_name=#1337 channel_topic channel_codec=2 channel_codec_quality=7 channe
l_maxclients=-1 channel_maxfamilyclients=-1 channel_order=0 channel_flag_permanent=1 channel_flag_semi_permanent=0 chann
el_flag_default=1 channel_flag_password=0 channel_codec_latency_factor=1 channel_codec_is_unencrypted=1 channel_flag_max
clients_unlimited=1 channel_flag_maxfamilyclients_unlimited=1 channel_flag_maxfamilyclients_inherited=1 channel_needed_t
alk_power=0 channel_n
RECV_CRYPT: ame_phonetic channel_icon_id=0
...
SEND_CRYPT: channelgetdescription cid=4 return_code=1:d
RECV_CRYPT: notifychanneledited cid=4 channel_description reasonid=9
RECV_CRYPT: error id=0 msg=ok return_code=1:d
SEND_CRYPT: clientmove cid=4 cpw clid=0 return_code=1:e
RECV_CRYPT: notifyclientmoved ctid=4 reasonid=0 clid=4
RECV_CRYPT: notifyclientchannelgroupchanged invokerid=0 invokername=Server cgid=8 cid=4 clid=4 cgi=4
RECV_CRYPT: error id=0 msg=ok return_code=1:e
SEND_CRYPT: connectioninfoautoupdate connection_server2client_packetloss_speech=0.0000 connection_server2client_packetloss_keepalive=0.0000 connection_server2client_packetloss_control=0.0000 connection_server2client_packetloss_total=0.0000
SEND_CRYPT: channelgetdescription cid=22 return_code=1:f
RECV_CRYPT: notifychanneledited cid=22 channel_description reasonid=9
RECV_CRYPT: error id=0 msg=ok return_code=1:f
SEND_CRYPT: clientmove cid=22 cpw clid=0 return_code=1:g
RECV_CRYPT: notifyclientmoved ctid=22 reasonid=0 clid=4
RECV_CRYPT: error id=0 msg=ok return_code=1:g
RECV_CRYPT: notifyclientchannelgroupchanged invokerid=0 invokername=Server cgid=8 cid=22 clid=4 cgi=22
...

Now it’s up to you to build Lua code that can inject command packets to test how the server is responding.

have fun,
Michael Willigens

8 Comments

Building an MMORPG Bot from scratch – Part1

Written by defragger on August 8, 2012 Categories: assembler, reverse engineering, windows Tags: , , ,

Part1 – Preliminaries and anti-hacking

With this post i will start a series of tutorials on what you have to do if you want to write a bot or tool for an MMORPG. This series will take the game Silkroad Online as example. It should give you an inside view to reverse engineering programs. As well as an overview about the common aspects and tools in game reversing.

The chapters

In this Chapter

  • Get rid of anti hacking counter measures
  • Make your debugger attachable
  • Make your own launcher

Requirements

  • Silkroad Online
  • A decent debugger: OllyDbg 2.X
  • A codecaving and injection framework: mmBBQ 3.X
  • An editor of your choice (mine is Vim ;) )

The most beginners have the problem not to know how to start. With a program like the selected mmorpg its really a hard task, cause its binary is 13MB large and is protected with hackshield.

First of all we will start the client and attach ollyDbg to it. (in olly File->Attach and select the process) Then we will see hackshield in action. It prevents from attaching a debugger to the given process. Hackshield does that with a kernel driver that is loaded by ehsvc.dll during sro_client.exe startup.

-32Bit they hook NtOpenProcess and return ACCESS_DENIED if someone tries to open Silkroad.
-64Bit they load a so called filterdriver (ObRegisterCallbacks) these callbacks will be called if someone tries to open or copy a handle to the specified process.
Another trick of hackshield is a cyclic scan of the loaded executable for changes.
If we start sro_client.exe without the loader we will get:

What to do next:
1. read the start parameters for the executable
Thats an easy task with the help of mmBBQ.
- Start Silkroad.exe
- use START.bat from out zip file for mmBBQ
- because we already have done most of silkroad
it will automatically injects into the process.
now just type

 str(asmcall.cdecl(getProcAddress("kernel32", "GetCommandLineA")))

in the mmBBQ console and you will see something like this:

 str(asmcall.cdecl(getProcAddress("kernel32", "GetCommandLineA")))
'"C:\Program Files (x86)\Silkroad\sro_client.exe" 1967664 /18 0 3'

If you have opened the sro_client.exe in ollydbg youre easy able to set the command line with
File-> Set new arguments…
2. Make sro_client.exe startable without the loader
We know the message that will occur when we try to start sro_client.exe directly.
- So we open the executable in ollyDbg (File->Open)
- Then we will search for all referenced Strings (right click -> Search for -> All referenced strings)
- In the new window we will search for the text “Please Execute” (right click -> Search for text)
null
- a double click on that line later we jump to the position where the string is used:
null
As we can see, right before the parameters for the call of MessageBoxA theres a conditional jump (JNE)
If we change this one to a unconditional one (JMP) (double click on the line)
3. get rid of hackshield
Searching for strings i a executable is not the most professional way of reverese engineering, but in the case of silkroad it will work really often :)
So simply search for HackShield like you search before.
null At this point scroll a bit up to get to the beginning of that function.
null In the window under the code section we can see

 Local call from 8BDC20.

Double click on that
and the same in the new occuring window to get to the position where our function is called. null
At the position where our function will be called till before the line with

 PUSH EBX

is the startup part for hackshield.
null right click -> Edit -> Fill with NOPs
null
Maybe i will add a detailed description why i choose this block but i want to move on to more interesting stuff :)
After all the hard work youre able to save the edited binary to another executable. right click -> Edit -> Select all, right click -> Edit -> Copy to executable and in the new window right Click -> Save to file. Choose another name then sro_client.exe (its cool to have a original backup :D)

So every time you want to live debug the client, just open the saved executable in olly (dont forget to set the arguments before you run run :D) and then klick run.

Greetz,
defragger

 

Edit:

I was asked to add more information about the nop block so here it comes :)

The interface  between HackShield and the secured process is contained in Ehsvc.dll. So if we want to prevent HackShield from beeing loaded, we have to ensure that this dll is not loaded. There are a few methods to find the place where Ehsvc.dll will be loaded:

Open Ehsvc.dll in ollyDbg and set a breakpoint at the entrypoint of this dll, after that open your fresh sro_client.exe and klick run. At the point LoadLibrary is called for this dll your process breaks at the entry. Youre now able to scroll down in the stack to see where LoadLibrary is called in the process:

null

Klick on the selected line to get to the point into the sro_client.exe, scroll up to the beginning of that function. If you select the first asm mnemonic there youll get

Local calls from 8BCE61, 0CA77B5

We follow the first ptr and see

ASCII \HackShield\EhSvc.dll

in the middle of that function. We follow up to the
call of that function and now we are already at the right position where we later will add our nop stuff :)
null
The easiest way is here to trial and error till its enough that you have nopped to get rid of hackshield. You can also follow up all calls on the shown place to check if there are hackshield specific functions. (I know its the trivial way cause silkroad contains so much usefull strings for us reverser :) )

Here the NOPed block with comments on what the calles actually do:

You can also breakpoint every called function in this block and step through (F7/F8) to get more information what this function does. I hope this helps to get to know what to nop :D
null

… You can also search for strings as we saw in the part before (EhSvc.dll, HackShield…). Thats much easier, but you wont learn from it.

15 Comments

Make OllyDbg 2.X scriptable

Written by will on August 4, 2012 Categories: assembler, reverse engineering, windows

Heya,

i would like to show a nice proove of concept on howto use mmBBQ 3.X to make any win32 cprogramm scriptable. For example ollyDbg 2.X.
First of all download: http://duschkumpane.org/mmbbq/releases/mmbbq_3.0.0.zip
. Unzip it and youll get a bunch of files. Youre able to use START.bat without changing anything to get a list of processes in your system that you could inject our mmbbq into.

Just select the index or pid of the process:
injector console

Youre also able to define a target in config.lua that mmbbq will injects into if the process is available. Our new Target looks like:

_G.TARGETS = { 
      ["name"] = "ollydbg",
      ["title"] = "OllyDbg",
      ["ver"] = "2.01 (alpha 4)",
      ["exe"] = "ollydbg.exe",
      ["lua"] = "olly_target.lua",
   },
}

The ["lua"] part defines the entry to the lua script for the new target. Just create olly_target.lua and add your
lua code that will be executed when you inject mmbbq into ollyDbg 2.0. Now its time for some reversing fun.
Just start ollyDbg and attach another to it, search in the attaching olly for “Names”. There you can find the exported olly functions:
http://praty.net/i/ollynames.jpg

There you can find for example Setint3breakpoint, if we set a breakpoint there and set a breakpoint in the other olly we will see how this function will be called.
http://praty.net/i/setint3call.jpg

A call from our lua API to Setint3breakpoint will now look like this:

function setBp(address)
  asmcall.cdecl(getProcAddress(0, "Setint3breakpoint"), address, 0x3001000, 0, 0, 0, 0x53E4B7, 0x53E4B7, 0x53E4B7);
end

I have done some additional functions:

function removeBp(address)
  asmcall.cdecl(getProcAddress(0, "Removeint3breakpoint"), address, 0x1000);
end

function findLabel(address)
  local buffer = new("wchar_t[255]");
  asmcall.cdecl(getProcAddress(0, "Findlabel"), address, buffer, 0);
  local label = dbg.readWStr(buffer_ptr, true);
  print(label);
end

function addLabel(label, address)
  local wlabel = char2wchar(label);
  asmcall.cdecl(getProcAddress(0, "InsertnameW"), address, 0x21, wlabel);
end

So we are able to find labels for a specific address, set labels, set and remove INT3 breakpoints from lua

Our POC in action:
Set and remove Breakpoints in ollyDbg from Lua (mmbbq) – YouTube video link

Additional information about mmBBQ: http://mmbbq.org
Feel free to ask or visit us at irc.freenode.net #duschkumpane

greetz defragger

No Comments

Dirty IAT deeds done dirt cheap

Written by will on July 11, 2012 Categories: assembler, reverse engineering

The following C macro rewrites an IAT jumptable entry of a module during runtime. Sometimes this can be very useful if linked libraries don’t support custom allocator function and such. We used it for a while to wrap any call to specific library functions for a given module: malloc/calloc/realloc and free (in our case). But we got scared of it ugliness after a while. Anyway, as its a very cool example of HOW-NOT-TO use pointer syntax… here we go:

// rewrite JMP to IAT i.e.:
// &malloc => 6C488670
// ==>  FF25 DC45916C : JMP DWORD PTR DS:[<&msvcrt.malloc>]
// ===> PTR to IAT    : (void*)(((char*)&malloc)+2)

#define IAT_FUCKUP(old_function, new_function) do{ \
    **(void***)(((char*)&old_function)+2) = new_function; \
} while(0)

Hard to read but yet effective. It basically rewrites an entry in the modules (DLLs) jumptable to a custom destination. Note: this can be used at least in gcc 32bit code, but it may work on others as well. The magic “+2″ comes from the fact that an address in a jumptable is located after a long jump command [/cc lang="asm"]JMP PTR:DS 0×12345678[/cci] codes: {0xFF, 0×25}. This pointers are located in the relocation section of your module.

In C code this macro can be used like this:

void* my_malloc(size_t size)
{
    printf("my_malloc called for %X bytes", size);
    // ... now wrap malloc or implement own allocator
}

int main(int argc, char *argv[])
{
    IAT_FUCKUP(malloc, my_malloc);

    // ... from now on any call to malloc
    // even hard linked libs etc will use
    // my_malloc for allocation
    void* foobar = malloc(0x10);
}

will

No Comments