codeblog code is freedom — patching my itch

February 5, 2011

fun with game memory

Filed under: Blogging,Debian,General,Reverse Engineering,Ubuntu — kees @ 5:15 pm

So, I was testing a (closed source) single-player offline game recently and thought this exercise might be fun to document. I didn’t want to spend any time actually earning in-game money since I’d played it before and I wanted to just skip ahead to other aspects of the game. I was curious how straight-forward adjusting my cash might be. So, noting the in-game “bank account number” of 219393 and account balance of 3000, I dived right in.

First up, what’s the memory layout of the heap look like? I looked at the brk and the mmap regions without a mapped library or file, marked with “w” in the permissions column, from /proc/PID/maps:

0827e000-08282000 rw-p 00000000 00:00 0
0a22e0000b08a000 rw-p 00000000 00:00 0 [heap]
efa59000-efd00000 rw-p 00000000 00:00 0
efd00000-efd21000 rw-p 00000000 00:00 0

Knowing these, I could use gdb’s “find” command, after attaching to the process:

$ gdb /some/cool/game

(gdb) attach PID

(gdb) find /w 0x0827e000, 0x08282000, 219393
(gdb) find /w 0x0a22e000, 0x0b08a000, 219393

No hits in the first region, but I see two hits for the account number value in the second region. Let’s start there and see what’s near them…

(gdb) x/8x 0xaf03d08
0xaf03d08: 0x00035901 0x00000000 0x00000000 0x0af06ce0
0xaf03d18: 0x0af06be0 0x00000059 0x0af03d98 0x0af041e8
(gdb) x/8x 0xaf06ca8
0xaf06ca8: 0x00035901 0x00000bb8 0x00000bb8 0x0820b148
0xaf06cb8: 0x00000001 0x00000000 0x00000000 0x00000000

In that second hit, I see the value 0xBB8, which is 3000, and matches our account balance. Let’s see what happens if we just change both of those to add a bit a few orders of magnitude above the current value…

(gdb) set var *0xaf06cac = 0x00100bb8
(gdb) set var *0xaf06cb0 = 0x00100bb8
(gdb) x/32x 0xaf06cac
0xaf06cac: 0x00100bb8 0x00100bb8 0x0820b148 0x00000001
(gdb) continue

And presto, clicking on the bank account details in-game shows a huge account balance of 1051576 now. No need to reverse-engineer any saved games, whew.

© 2011, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 License.
CC BY-SA 4.0

August 12, 2010

CryptProtect broken

Dan Rosenberg pointed me to a paper from the 2010 WOOT conference that mentions my work to implement the CryptProtect function in Wine. Their research is awesome, and it was fun to compare my attempts at identifying the blob structure to what they discovered. Looks like I got the structure pretty well, but that was easy; they totally broke the encryption itself. Now those native blobs can be decrypted, opening the door to full NTFS interoperability, offline forensics of Windows encrypted files, etc. (For designers of future symmetric encryption methods: please don’t store the keys (in any form) on disk with the cipher text…)

What I found most alarming about this is a comparison to eCryptfs, and how it is implemented with the user’s login passphrase. In both cases, a hash of the passphrase is used to perform additional work that results in keying the final encryption. In eCryptfs, this hash is calculated to unlock the main key that is used for eCryptfs and is then thrown away (it can always be regenerated when the user logs in). If the user changes their passphrase, they must decrypt and re-encrypt the eCryptfs key (this is done automatically by PAM). Under Windows, to deal with potential user login passphrase changes, they instead decided to store all prior (SHA1) hashes of the user’s passphrases, even lacking a salt. So all the clear-text user login passphrases are recoverable with a standard rainbow table, in parallel. O_o

© 2010, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 License.
CC BY-SA 4.0

February 13, 2009

World Of Goo compiled on Ubuntu

Filed under: Blogging,Debian,Reverse Engineering,Ubuntu — kees @ 3:44 pm

I first played World of Goo on the Wii. I loved it. Great stuff, reminded me a little of Lemmings, but way way better. Today I found out it’s also available for Linux, and I immediately downloaded it. I was pleased to see a .deb available and thought I’d dig into the binary a little to see how it was put together.

I’m hugely excited to see that it looks like the game was built on Ubuntu Intrepid for both the .deb and .tar.gz packages:

$ strings -a WorldOfGoo.bin | grep -i gcc
GCC: (Ubuntu 4.3.2-1ubuntu12) 4.3.2

The bundled libraries appear to come from Gentoo:

$ strings -a libs/ | grep -i gcc
GCC: (GNU) 4.2.3 (Gentoo 4.2.3 p1.0)

OpenSSL (and libpng?) from Gentoo seem to have been statically linked into the binary:

$ strings -a WorldOfGoo
GCC: (GNU) 4.2.3 (Gentoo 4.2.3 p1.0)

What I’m so very excited about is that third party software producers are using Ubuntu for their releases. This means they get all the security and code-quality improvements that are built into the Ubuntu compiler for free:

$ objdump -CR WorldOfGoo.bin | grep _chk
084043f0 R_386_JUMP_SLOT __memcpy_chk

Many thanks to Maks Verver for doing the porting. I’m really enjoying the demo. Also, I can see your devel path! :)

$ strings -a WorldOfGoo.bin | grep openssl
OPENSSLDIR: "/home/maks/Projects/wog/libs/openssl-0.9.8j-linux-i386/ssl"

All this said, it may be that they’re actually only compiling pieces (like the Open Dynamics Engine, which seems to contain the bulk of the *_chk calls) on Ubuntu (or using .a files from a distro-compiled library that enables hardening only in builds — RedHat, SuSE), but doing the .deb and .tar.gz project linking on Ubuntu (which is why the compiler name shows up in the resulting binary). The RPM shows the *_chk functions too — actually the disassembly is identical between deb and RPM, which would imply that only final linking was done on the native distros but compiled elsewhere. I’d love to hear more details if Maks stumbles on this blog. :)

© 2009, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 License.
CC BY-SA 4.0

September 15, 2007

catching stack overflows in gdb as they happen

Filed under: Reverse Engineering,Security,Ubuntu — kees @ 8:57 pm

Recently I was trying to help debug a stack overflow crash in wpa_supplicant. The trouble with a stack crash is that you end up without a useful call history since the stack is left partially wrecked. The compiler code for detecting stack overflows (SSP), sets up a canary value between the local variables of the function and the stack frame. When the function exits, it tests this canary value and aborts if it doesn’t match what it is expecting. So, logically, to catch the stack overflow, gdb needs to be set up in a way to watch the canary location too. Since the canary is only valid while in the function, gdb must be set up to have a memory watch only when the function is called.

Here is the function preamble:

0x08081940 <wpa_driver_wext_get_scan_results+0>:        push   %ebp
0x08081941 <wpa_driver_wext_get_scan_results+1>:        mov    %esp,%ebp
0x08081943 <wpa_driver_wext_get_scan_results+3>:        push   %edi
0x08081944 <wpa_driver_wext_get_scan_results+4>:        push   %esi
0x08081945 <wpa_driver_wext_get_scan_results+5>:        push   %ebx

Save registers, prepare %ebp.

0x08081946 <wpa_driver_wext_get_scan_results+6>:        mov    $0x1000,%ebx
0x08081951 <wpa_driver_wext_get_scan_results+17>:       mov    0x8(%ebp),%eax
0x08081954 <wpa_driver_wext_get_scan_results+20>:       mov    0xc(%ebp),%edx
0x08081957 <wpa_driver_wext_get_scan_results+23>:       lea    0xffffffb0(%ebp),%esi

Make room for local variables, copy some function arguments and local variables into registers.

0x0808195a <wpa_driver_wext_get_scan_results+26>:       mov    %gs:0x14,%ecx
0x08081961 <wpa_driver_wext_get_scan_results+33>:       mov    %ecx,0xffffffec(%ebp)
0x08081964 <wpa_driver_wext_get_scan_results+36>:       xor    %ecx,%ecx

Here’s the stack canary getting set, and the register cleared. It’s saved at %ebp minus 0x14 (0xffffffec signed is -0x14):

(gdb) printf "0x%x\n", 0-0xffffffec

Now for the function play-out:

0x08081a37 <wpa_driver_wext_get_scan_results+247>:      mov    0xffffffec(%ebp),%edx
0x08081a3a <wpa_driver_wext_get_scan_results+250>:      xor    %gs:0x14,%edx
0x08081a41 <wpa_driver_wext_get_scan_results+257>:      jne    0x8081eae <wpa_driver_wext_get_scan_results+1390>

There is the canary check.

0x08081a47 <wpa_driver_wext_get_scan_results+263>:      add    $0xec,%esp
0x08081a4d <wpa_driver_wext_get_scan_results+269>:      pop    %ebx
0x08081a4e <wpa_driver_wext_get_scan_results+270>:      pop    %esi
0x08081a4f <wpa_driver_wext_get_scan_results+271>:      pop    %edi
0x08081a50 <wpa_driver_wext_get_scan_results+272>:      pop    %ebp
0x08081a51 <wpa_driver_wext_get_scan_results+273>:      ret    
0x08081eae <wpa_driver_wext_get_scan_results+1390>:     call   0x804bdc8 <__stack_chk_fail@plt>

Release local stack, pop saved registers and return. Nearer the end is the call to __stack_chk_fail when the canary doesn’t match.

So, to watch the canary, we need to set up a memory watch after it as been set, and tear it down before we leave the function. Respectively, we can use addresses 0x08081964 and 0x08081a3a (in bold above):

(gdb) br *0x08081964
Breakpoint 1 at 0x8081964
(gdb) br *0x08081a3a
Breakpoint 2 at 0x8081a3a

At the first breakpoint, we set a memory watch using a gdb-local variable, based on %ebp (we can’t use %ebp directly since it will change in lower function calls):

(gdb) commands 1
Type commands for when breakpoint 1 is hit, one per line.
End with a line saying just "end".
>set variable $cow = (unsigned long*)($ebp - 0x14)
>watch *$cow

Since I couldn’t find an easy way to track the memory watch number that was created during the first breakpoint, I just built a gdb counter, and deleted the memory watch when leaving, since I could predict gdb’s numbering (first watch will be “3”, following our breakpoints 1 and 2):

(gdb) set variable $count = 3
(gdb) commands 2
Type commands for when breakpoint 2 is hit, one per line.
End with a line saying just "end".
>delete $count
>set variable $count = $count + 1

Now we can run, and wait for the canary to get overwritten:

(gdb) cont
Hardware watchpoint 3: *$cow
Hardware watchpoint 4: *$cow
Hardware watchpoint 12: *$cow
Hardware watchpoint 13: *$cow
Hardware watchpoint 13: *$cow

Old value = 4278845440
New value = 4278845546
0x0804eae6 in ?? ()

We see the canary value is 0xFF0A0000 getting it’s little-endian first byte overwritten to FF0A006A. We catch it before it has wrecked the stack, and we can see very clearly where we are:

(gdb) bt
#0  hexstr2bin (hex=0x080a239d "6151663870517a74", buf=0x080a2395 "aQf8pQzt00000000j", len=8)
    at ../src/utils/common.c:88
#1  0x08082297 in wpa_driver_wext_get_scan_results (priv=0xb7dd816c, 
    results=0x080a239d, max_size=0x79)
    at ../src/drivers/driver_wext.c:1383
(gdb) x/1i $eip      
0x804eae6 <hexstr2bin +54>:      addl   $0x1,0xfffffff0(%ebp)

On a closer look at the source, we realize wext_get_scan_custom got inlined into the function (it was static and only called from one place, so the compiler optimized it). Further tracking in the source shows that the “16” value passed in should actually be “8” (the limit of the destination, not the source, buffer size).

© 2007, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 License.
CC BY-SA 4.0

August 7, 2007

flag captured again

Filed under: Reverse Engineering,Security — kees @ 4:22 pm

I thought last year was going to be a fluke. Somehow we managed to do it again. Team 1@stPlace won DefCon Capture the Flag for a second year in a row. If my sources are correct, this is the first repeat CTF winner at DefCon since the Ghetto Hackers. I’m honored to be on such a very talented team. I’ve only just recently recovered from getting almost no sleep for 3 days. :)

© 2007, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 License.
CC BY-SA 4.0

August 7, 2006

flag captured

Filed under: Reverse Engineering,Security — kees @ 11:19 pm

I can’t believe it. We won DefCon CTF. I have no idea what to say. It just all came together this year. Great team, great contest.

And to make it even sweeter, since CTF is a “Black Badge” contest, I never have to pay to get into DefCon again! Although, at this point, I might pay several years worth of admission in exchange for lots of time to sleep. :)

UPDATE: nice write-up at the U of Florida.

© 2006, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 License.
CC BY-SA 4.0

January 17, 2006

ngsec games

Filed under: Reverse Engineering,Security — kees @ 5:49 pm

Today I was reminded of the NGsec security games site from a DefCon CTF team-mate. (This game was actually used as a prequal for DefCon 10, which I didn’t go to. Ken told me stories about it, though.) I burned through stages 1-9 in about 45 minutes, and then hit stage 10 and was side-tracked learning about encrypted ELF binaries.

There continues to be no useful FOSS binary analyzers for this kind of reverse engineering. gdb just doesn’t even begin to cut it: it was made for (surprise!) debugging programs built by friendly compilers, not doing forensics on decidedly unfriendly, hand-crafted binaries . If Paul Graham and Richard Hamming are to be believed:

  1. What are the most important problems in your field?
  2. Are you working on one of them?
  3. Why not?

I should be writing a static binary analyzer. And a dynamic one too. GPL IDApro replacement. Yeow.

© 2006, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 License.
CC BY-SA 4.0

October 19, 2005

color printer tracking

Filed under: Reverse Engineering,Security — kees @ 3:28 pm

I’m a little behind in my Slashdot reading, so apologies to those that saw this earlier.

The EFF cracked the nearly invisible finger-printing code produced by color printers. This system is used by most (if not all) major color printer manufacturers to report the serial number of the printer used and the date a page was printed. This system has been in place for at least 10 years. I’m horrified at this kind of privacy invasion. To quote the EFF:

“Underground democracy movements that produce political or religious pamphlets and flyers, like the Russian samizdat of the 1980s, will always need the anonymity of simple paper documents, but this technology makes it easier for governments to find dissenters,” said EFF Senior Staff Attorney Lee Tien. “Even worse, it shows how the government and private industry make backroom deals to weaken our privacy by compromising everyday equipment like printers. The logical next question is: what other deals have been or are being made to ensure that our technology rats on us?”

EFF press release:
Washington Post coverage:

© 2005, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 License.
CC BY-SA 4.0

September 22, 2005

decompiling myself

Filed under: Health,Reverse Engineering — kees @ 9:01 pm

Figured I should try to decompile myself. The first step would be get a full dump of my DNA base pairs as letters. Looks like that’s not going to be easy though. Even a DNA stain takes a lot of steps (and I’ll probably never be allowed to do the radioactive steps myself). The real goal here is that with current US law, I should copyright myself (I’m the first performance of the specific base pair “idea”) and possibly patent myself (my methods are a unique variation of other methods).

Obviously this doesn’t take into account my immune system or my memories, but I figure it’s a good start. At like just under 10 billion base pairs, that’s a 10GB program. I think Inkscape is only 45M or so, and that’s not even counting shared libraries.

Since I don’t really want to share my DNA with a company (I’ve got to be the first to copyright it), I wanted to find out what it would take to sequence at home. Since a sequencer is in the $100k price range, that’s not really going to happen. Talking to my NIH-employed friend techne23, she suggested a possible “cheap” way to do it would be in pieces, doing PCRs on specific SNPs, and send those out for sequencing to get back base pair letters. For example, on a gene, the red ones here are considered “interesting”. The PCR machines can be had for cheap, too.

So, in summary:

  • need all the standard lab stuff (centifuge, gloves, tips, pipets, tubes, autoclave, glassware, etc)
  • need chemicals to isolate my DNA
  • need a little space in my freezer to store my DNA
  • need to buy PCR reagents, about $100 for 50-100 reactions
  • need two base pair-specific primers at $40 total for up to 500 base pairs per PCR
  • need thermal cycler to do the PCR in
  • need electrophoresis equipment to see if the PCR worked (maybe reuse my UV EPROM wiper?)
  • need toxic (careful!) reagents for the electrophoresis
  • need a sequencing company that is willing to work with a non-University
  • need FedEx account to ship PCR to sequencers :)

Or I can spend crazy money doing thousands of SNPs at once in microarrays. (Or wait until they’re in every doctor’s office.)

© 2005, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 License.
CC BY-SA 4.0

August 29, 2005

open source disassemblers

Filed under: Reverse Engineering — kees @ 7:57 pm

Not a lot of OSS folks seem to be interested in reverse engineering, so as a result, there isn’t anything like IDA-Pro for the OSS reverse engineer. There is a very excellent disassembling library, but it has no user interface (yet). It used to have Bastard attached, but that’s pretty out of date now. There is also Lida, but it doesn’t even compile. It was based on Bastard, but I can’t get it to work. It seems to be missing some specific version of the opcode map from Bastard.

Bastard and Lida are both static analysis tools, though. What I really want is a dynamic analyzer. I want to be able to trace the call paths during Porrasturvat’s execution, so I can more easily figure out which function is called when I click “Dismount”. That’ll help me find the Force constant. I’m worried I’m going to have to hack together some unholy Perl script to run “stepi” over and over, waiting for each “call” to take place. That. Would. Be. Very. Slow.

Anyway, I was really impressed with libdisasm, so I built an automake/autoconf setup for it. Even if they don’t want it, I like being able to do a “make install” and having the library end up in the right place. :)

© 2005, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 License.
CC BY-SA 4.0

August 28, 2005

porrasturvat hacking

Filed under: Reverse Engineering — kees @ 2:14 pm

Three years ago, when I first saw tAAt’s Porrasturvat, I couldn’t stop playing it all day. It’s a really simple game: see how much “damage” you can score to a stick figure that you push down the stairs. It’s basically a physics simulation that tracks force and impact of a body falling down a flight of stairs. So much fun. I hope they make it skinnable. :)

At the time (2002-11-12) I had asked for source code in the hopes of helping to port it to Linux. I got an email yesterday in reply to my request. This sets the record for the longest reply-time on a email, ever. :) Jetro was letting me know it was available for Linux now, so I immediately downloaded it and started playing again. This version is much more stable and lacks any scoring glitches (that I’ve been able to find), so it’s a real challenge to get a high score.

Even in the original game, I had wanted to push the figure backwards off the stairs to see what kind of damage would be done just from having him fall straight down. This time, I’m determined to practice some binary analysis skills and locate the place in memory where the “Force” value is kept so I can tweak it. So far so good, I’ve been able to locate the damage accumulators for the various body parts. Now it’s a matter of just tracing the changes back through the execution paths. Here’s my million-point game:

damage mod

© 2005 – 2015, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 License.
CC BY-SA 4.0

cvs camcorder

Filed under: Multimedia,Reverse Engineering — kees @ 12:43 am

I was able to get my hands on a CVS camcorder this past week. The unit is very cool. It doesn’t have any features of a “real” video camera, but I view it like a super-version of my Digital camera which can take 15 seconds worth of video at a time. This one is only limited by available storage (about 20 minutes). The resolution can be turned up to 640×480, too.

Initially I couldn’t get a cable built for it. I had a spare USB cable and a spare Palm Pilot cable to merge, but after soldering it all together, the device wouldn’t take an address (but my laptop noticed it was getting plugged in). After a hint from Linus (“plug-ins are detected via power-draw, everything else is over the data lines”), I realized that perhaps the USB data wires were reversed (the cable has got to flip them on at least one end of the cable… I just got unlucky).

The software for downloading the videos had been ported to Linux, and I worked on some more code to have a one-shot ability to download all the videos from the camera. Now I’ve got autoconf/automake working for it, and have gotten myself added to the Saturn Tools project where we can all work on the code through SourceForge’s CVS. Much easier than endlessly trading patches. :)

So far, I’ve managed to wreck the splash-screen image during camera bootup. Something is busted with the usb_bulk_write calls, and the device stops taking writes after 4k worth of data. Hopefully I can get that repaired so I can be greeted by the Laughing Man. I’ve also got a JPG all ready to replace the logo screen, “powered by pure digital technology”, with my oh-so-clever “powered by pwnd digital technology”.

© 2005 – 2016, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 License.
CC BY-SA 4.0

July 13, 2005

pattern visualization

Filed under: Reverse Engineering — kees @ 7:59 pm

Damn. I just thought up another piece of software (that I’m capable of writing) that I can’t find. This is bad; it means it’s going to haunt me until I code it.

So, frequently, I’m faced with streams of bytes of unknown origin/purpose. (For example, the .TiVo file format, RTMP streams, and most recently, Outlook “NK2” address autocompletion cache files.) I’ve had experience finding patterns, but it’s always so time-consuming. Usually I’m compiling some little C program over and over, slowly tweaking some guessed-at structure. This is basically the advice I got from Andrew Tridgell when I asked how he went about reverse engineering protocols. His methods deal more with sending/receiving, so it’s much more interactive. Most of what I’ve mucked with are just unknown file formats.

What I want is a nice GUI tool that will let me specify a language to describe a data file’s contents. I can see lots of meta-specifications like “repeat this structure until EOF”, and “if byte 5 is 1, read X bytes, otherwise, read X+50 bytes”, etc. Most data formats have pretty simple layouts after you figure them out. As you create the structure for the data to fit into, you can see the data from your example file displayed live. This way you can quickly tweak lengths, offsets, encoding types, endianness, etc, without needing to totally recompile your test harness.

Hell, it could even spit out the C code to process it, too. :)

I’m thinking about using Gtk and Python. We’ll see how rapid that path is for developing a nice GUI. I’ve heard good things. :)

© 2005, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 License.
CC BY-SA 4.0

February 25, 2005

.tivo file format

Filed under: Multimedia,Reverse Engineering — kees @ 1:35 am

After I found some details on the .tivo file format, and cooked up some code to produce the same output. So far, there isn’t a lot of detail. It’s mostly just strange stuff. mpegcat finds the MPEG2 stream right where it should be, but supposedly the non-I-frames appear to be encoded.

All the files I’ve downloaded from my TiVo have the same “fingerprint” listed in the XML header, and a different “salt”. The interface for downloading recordings is very simple. Connect to https://[tivo IP]/ and it’ll prompt you for your username and password, which is “tivo” and your “Media Access Key”. After that, you’re all set; browse away. Download speed is rather slow: 500kB/s. Better than 2400 baud. :)

© 2005, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 License.
CC BY-SA 4.0

February 16, 2005

Hitchhiker’s Guide to Reverse Engineering

Filed under: Networking,Reverse Engineering — kees @ 7:53 pm

Well, I got annoyed that I couldn’t watch the SWF-based HitchHiker’s trailer on the main page. swf_play failed miserably. Most of the crap Apple pulls for their movie trailer stream-hiding is simple enough to work around. Generally I just keep downloading the MOVs, running strings on them until I find the actual MOV with the movie trailer in it, but Amazon’s wasn’t so easy. I found the base URL to the video easily enough in the XML parameters file. The hard part was figuring out what the hell “rtmp” is. mplayer didn’t recognize it, and after a quick nmap of the media server, I just got more confused. nmap listed a port 1935 called “rmtp”. Digging around a little it became very obvious that nmap’s services entry was just a typo. So I sent in a quick patch, and Fyodor accepted it within minutes. Pretty cool.

Anyway, on to the protocol dissection. I set up tcpdump to record everything sent to, and took a look at it in Ethereal. Seeing that it was mostly binary, I looked around for something that would dump the data portion of a packet stream, but ended up empty handed. I’ve repeatedly wanted this, so I finally broke down and read up on coding with libpcap. It’s easy enough to use, but I floundered with the packet headers for a while. Eventually I managed to find the data portion of the packets, and was able to dump the client stream and the server stream separately. I wish there was a button on Ethereal’s “Follow TCP Stream” window that would just let me save the data. My tool doesn’t at all track sequence numbers or retransmissions, etc, so I worry that in some situations I won’t get a “true” stream dump. I suspect Ethereal handles that correctly, but I couldn’t tell you for sure.

After looking at this protocol dump, it seems like it ends up turning into some kind of SOAP-like communication, with function call literals like getStreamLength, createStream, play, and closeStream. There’s even a _result variable mentioned. The Flash coding docs I’ve found that talk about stream display don’t seem to mention this stuff at all, but maybe I didn’t dig far enough.

Since RTMP appears to be capable of streams, etc, I think the next step is to figure out how it reacts to things like “Pause” and “Stop” during playback. Clearly there is a stream-identification system in the headers, and there must be stream length indicators. I’m so annoyed that there is absolutely no discussion of RTMP anyway. I should go look at the swf_play source before I go much further.

© 2005, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 License.
CC BY-SA 4.0

Powered by WordPress