yumBBQ TeamSpeak 3 Tutorial (mmBBQ 3.0.3)

Asphyxia

Server Monkey
Administrator
Joined
Apr 25, 2015
Messages
1,048
Points
237
Age
25
Location
North America
A better option may be found here https://r4p3.net/threads/c-ts3hook.5671/#post-50075

---


  1. Download this archive, extract it somewhere: https://r4p3.github.io/zips/yumBBQ3.0.3.zip
  2. Launch the 32-bit TeamSpeak 3 client.
  3. Execute START.bat as an administrator.
  4. Find the TeamSpeak 3 process ID, type it in and press enter.
  5. Connect to a server, watch the command-line console populate with data.
Did it work? Hopefully it did, if not then figure out what is wrong (try) and then let's move on.

The following information is mostly from: http://www.blizzhackers.cc/viewtopic.php?p=4597974

Edit your config.lua file, at the bottom where you see:
Code:
    if recv > 0 then
        printf("[RECV] 0x%X", recv);
        hexdump(buf, recv);
    end
Replace that if statement with:
Code:
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 … :]

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 typedbg.asm(0x009037D0, 7) into the Lua console and we will get:
Code:
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:
  • load the next DWORD to EDI (from the buffer pointer EDX)
  • decode the data using XOR and a stream source object or class (ECX+0×94)
  • increment the streamsource ECX by 0×4 (sizeof(DWORD))
  • write out the decrypted data to the original buffer (we catched that instruction earlier)
  • also increment output pointer EAX (used in the last instruction)
  • 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)


… 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.
Code:
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.
Code:
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
...
Good freaking luck, I hope you can figure something out and share it here lol --- I am working with it to try to figure out what I can do. :cool:
 
Last edited:

Derp

Retired Staff
Joined
Apr 30, 2015
Messages
916
Points
217
I'll do some tests in my XP Machine. Thanks for posting this :D
 

Bluscream

Retired Staff
Contributor
Joined
May 8, 2015
Messages
959
Points
171
Location
Germany
If yumBBQ is yours, why don't you implement what you just explained by default?

Somehow i dont get how to replace the dbg.printStack() stuff in the console with the decrypted query like commands.
 

Derp

Retired Staff
Joined
Apr 30, 2015
Messages
916
Points
217
@Asphyxia
What do you think the "Authentication" Packets Chunk Length can be? We could just Log and BreakPoint the "Important" Packets, Skipping all the rest.

Correct me if I'm Wrong.

PS: It's Weird, If i try to connect to some random server I get ACCESS_VIOLATION Errors, BUT That does not happen if I connect to LocalHost... o_O

EDIT: Unfortunately I'm Unexperienced in this kind of stuff, sorry if my questions sound a bit Noobish :|
 
Last edited:

Asphyxia

Server Monkey
Administrator
Joined
Apr 25, 2015
Messages
1,048
Points
237
Age
25
Location
North America
If yumBBQ is yours, why don't you implement what you just explained by default?

Somehow i dont get how to replace the dbg.printStack() stuff in the console with the decrypted query like commands.
yumBBQ is mine in the sense that I literally erased all of the unnecessary files that normally come with mmBBQ 3.0.3 and am making it freely/publicly accessible. If you were to try to find mmBBQ 3.0.3 elsewhere it would require you to register for it, there would be extra unnecessary configuration files, licenses and I figured I would just zip up a lightweight easy to use package of it.
Our approach is to inject an open, scriptable Lua API to the native game client. It is super-easy to use without any modification or depencies required. Just start your game and then mmbbq.
It was primarily developed for use with games. It turns out their method works very well with other software. You can for example sniff out and read where Player 1's head is, then send a bullet at Player 1's head probably requiring math. The possibilities with mmBBQ 3.0.3 are almost limitless when it comes to working with 32-bit software. It is important to note that this is the final version of mmBBQ and if that forum went offline --- pretty much no one would find mmBBQ 3.0.3 again, probably ever. yumBBQ sounds better, it is more lightweight and in the future I plan on including a version with a step-by-step tutorial on how we reverse the TeamSpeak 3 protocol successfully, when that time comes.

The below quote explains mmBBQ quite a bit better than I did:
mmBBQ injects an interactive codecaving Lua API into a win32 process. It is easy to use, there are no dependencies and only little knowledge is required. It was initially built to create APIs for MMORPGs. However it is fully generic and can attach to any kind of program. It can also inject into many protected processes, as it's meant to bypass some protective mechanisms. It offers debugging functionality, but not being a debugger itself makes it harder to detect.

It's easy to place any form of generic codecaves by using plain Lua code (LuaJIT C-Types). For Example:
codecave.inject(nil, getProcAddress("user32", "GetMessageA"), function(context) print("Hellow World Codecave") end)

It can also call arbitrary functions of the host process:
asmcall.cdecl(getProcAddress("user32", "MessageBoxA"), 0, "Hello World!", "Title", 0)

Aside that it includes a debugging and disassembly module, that can be used to script breakpoints. This can be useful when making packed .exe extractors etc.


64 bit support is underway. And further future maybe also a Linux and Mac version.
The authors of mmBBQ are both Michael Willigens and Rene Laemmert. They have not worked on the project in a longtime, so I believe it is fair to say the project is pretty much dead. It still works very well though for what it does.

It's basically a a disassembler which makes a program work itself backwards from my understanding. Since it was so hard to find and the project is seemingly on its way out, I figured why not rename it to yumBBQ, it is easier to spell also. When I first heard "mmBBQ", I thought it could possibly be spelled "mmmBBQ" --- it could be confusing.
 
Last edited:

dedmen

Developer
Joined
Mar 28, 2016
Messages
531
Points
157
Location
Germany
Do you have a copy of the Lua documentation like this one: http://archive.is/w0IqU ? I have an old mmbbq build with a ton of lua code included where i can find some things but thats tedious.


Btw heres my script for client 3.0.18.2 win32

Code:
offset = ffi.cast("int",dbg.getModule("ts3client_win32.exe").ImageBase);

file = io.open ("yummy.log" , "a")

local function decrpyt_hook(context)
    local length = cast("int", context.reg32.edi);
    if length > 5 then
            local charptr =cast("char*", context.reg32.ebp);
            if (charptr[0] < 0x60)  or (charptr[0] == 'G') then
            charptr =cast("char*", cast("int", charptr) + 11)
            end
   
            file:write("RECV_CRYPT: %s".. str(charptr, length).."\n");
            printf("RECV_CRYPT: %s", str(charptr, length));
    end
end
codecave.inject(nil,offset+ 0x59C46E, decrpyt_hook)--, codecave.INTERCEPT_RETURN

local function encrypt_hook(context)
        local length = cast("int", context.reg32.ebx);
        if length > 5 then
            file:write("SEND_CRYPT: %s", str(cast("char*", context.reg32.ecx), length).."\n");
            printf("SEND_CRYPT: %s", str(cast("char*", context.reg32.ecx), length));
        end
end

codecave.inject(nil, offset+0x59D429, encrypt_hook)--, codecave.INTERCEPT_PRE
 
Last edited:

TiREX

Member
Joined
May 7, 2015
Messages
15
Points
38
Location
Europe
When i use codecave.debug(address) yumBBQ give me error in console:
Code:
[ERR] 11:33:36 luacall.c   lua_exception_recovery() caught EXCEPTION code 0xC0000005 at address 0x764ED09C
[ERR] 11:33:36 LUA_TRACE   FATAL: ACCESS_VIOLATION in underlying lua or native code!
[ERR] 11:33:36 LUA_TRACE   [1] [C](-1): dbg_print_stack_C
[ERR] 11:33:36 LUA_TRACE   [2] [string "common/dbg.lua"](104): printStack
[ERR] 11:33:36 LUA_TRACE   [3] [string "common/codecave.lua"](176): (null)
how to correct this?

i have windows 7 64bit
i use teamspeak 3.0.17 32bit

@Supervisor
 
Last edited:

h3ku

Member
Joined
Oct 6, 2016
Messages
4
Points
33
Age
23
When i use codecave.debug(address) yumBBQ give me error in console:
Code:
[ERR] 11:33:36 luacall.c   lua_exception_recovery() caught EXCEPTION code 0xC0000005 at address 0x764ED09C
[ERR] 11:33:36 LUA_TRACE   FATAL: ACCESS_VIOLATION in underlying lua or native code!
[ERR] 11:33:36 LUA_TRACE   [1] [C](-1): dbg_print_stack_C
[ERR] 11:33:36 LUA_TRACE   [2] [string "common/dbg.lua"](104): printStack
[ERR] 11:33:36 LUA_TRACE   [3] [string "common/codecave.lua"](176): (null)
how to correct this?

i have windows 7 64bit
i use teamspeak 3.0.17 32bit

@Supervisor
Same here, I try with local server and remote server but I'm getting ACCESS_VIOLATION every time.

Any advice? @Derp @Asphyxia
 

h3ku

Member
Joined
Oct 6, 2016
Messages
4
Points
33
Age
23
I can confirm they are using AES in CRT mode with libtomcrypt to cipher all the messages.
I extract de IV and the KEY using ollydbg but the problem is this two values changes in every computer.

The client needs to say to the server what key and iv is using so its send this values on the firsts requests I think.
 

Derp

Retired Staff
Joined
Apr 30, 2015
Messages
916
Points
217
Reversing a little bit I see they use this to encrypt operations.

http://opensource.apple.com/source/CommonCrypto/CommonCrypto-55010/Source/libtomcrypt/src/modes/ctr/ctr_encrypt.c

Source (Decompiled function of decrypt):
eax5 = (int32_t)eax2("LTC_ARGCHK '%s' failure on line %d of file %s\n", "pt != NULL", 33, "c:\\jenkins\\workspace\\clientwindows_gyp\\deps\\ts_tomcrypt\\src\\modes\\ctr\\ctr_encrypt.c");
Wrong block mode, getting close tho ;)

As for the access violation error, The offsets are only working on 3.0.12.4


I can confirm they are using AES in CRT mode with libtomcrypt to cipher all the messages.
Wrong :3
 

h3ku

Member
Joined
Oct 6, 2016
Messages
4
Points
33
Age
23
Wrong block mode, getting close tho ;)

As for the access violation error, The offsets are only working on 3.0.12.4




Wrong :3
Really? xD

Fuck I miss something xD

Am I correct with the part of the client using different keys in different computers? Or always the same?

I reach to the conclusion of CTR mode because of this.


When any network request starts the program call to the initialization of the ctr cipher mode.

@Derp
 
Last edited:

RSX

New Member
Joined
Dec 18, 2016
Messages
49
Points
20
Age
87
mmbbq is highly deprecated and there's alternatives to this, if you so desire lua so much.
a) Why would you want to rebrand something that isn't yours?
b) Why do you want lua so bad?

Really? xD

Fuck I miss something xD

Am I correct with the part of the client using different keys in different computers? Or always the same?
@Derp
Yes, a lot. Break pointing one or two things in x32dbg is no where near enough. There's zero point in explaining the auth flow as it is pretty much pointless to someone who can't find it themselves. Something that may be of note worthy when doing research is that, spamming 'xD' doesn't help you in anyway.

Reversing a little bit I see they use this to encrypt operations.
http://opensource.apple.com/source/CommonCrypto/CommonCrypto-55010/Source/libtomcrypt/src/modes/ctr/ctr_encrypt.c
Source (Decompiled function of decrypt):
eax5 = (int32_t)eax2("LTC_ARGCHK '%s' failure on line %d of file %s\n", "pt != NULL", 33, "c:\\jenkins\\workspace\\clientwindows_gyp\\deps\\ts_tomcrypt\\src\\modes\\ctr\\ctr_encrypt.c");
Wow, master reverse engineer in the fucking house! Setting a memory write break point then googling a string ref isn't praise worthy. Next time, actually link the "official" (new maintainers) libtomcrypt repo and not some apple branch.
 

Derp

Retired Staff
Joined
Apr 30, 2015
Messages
916
Points
217
b
a) mmbbq is highly deprecated and there's alternatives to this, if you so desire lua so much.
b) Why would you want to rebrand something that isn't yours?
c) Why do you want lua so bad?
a) Any suggestions? feel free to create a new issue on our git repo: https://github.com/R4P3NET/yumbbq

b) I don't think we are rebranding mmbbq, mmbbq is a lua scripting api Quote, so, basically we took the already available api and adapted it to our needs.

c) We don't, It has nothing to do with lua. We wanted to start things off using already available information, such as the blizzhackers thread on teamspeak reverse engineering (This). And since we didn't have any problems with lua or mmbbq, we didn't bother looking for alternatives
 

RSX

New Member
Joined
Dec 18, 2016
Messages
49
Points
20
Age
87
b

a) Any suggestions? feel free to create a new issue on our git repo: https://github.com/R4P3NET/yumbbq

b) I don't think we are rebranding mmbbq, mmbbq is a lua scripting api Quote, so, basically we took the already available api and adapted it to our needs.

c) We don't, It has nothing to do with lua. We wanted to start things off using already available information, such as the blizzhackers thread on teamspeak reverse engineering (This). And since we didn't have any problems with lua or mmbbq, we didn't bother looking for alternatives
Apart from move to c(++), use patterns, and fuck deprecated software, I have nothing else to add. Furthermore, releasing or even contributing to public utilities is just going to be a bad idea. This isn't intended to be taken personally, but you have members that are twats and complete skids, therefore, the last thing I (or anybody with a shred of integrity) want to do is release anything related to auth and the crypto, even if it is to get the retards that think it's purely plain text to shut the hell up. Talking from experience, all people do with said resources is just completely fuck up the platform and the communities they belong to. As for b, I get ya now.
 
Last edited by a moderator:

NoXx

Member
Joined
Apr 24, 2016
Messages
33
Points
50
Location
Switzerland
Someone tested this with the actual client version? I couldn't get it to work and I gave up after 3,5 hours :p

Best regards
 

Top