Often times when reversing a binary we get the idea stuck in our head that everything we are looking at is closed source; a secret. In most cases I this is true, let's take a look at an example where the application of some lateral thinking provides a huge shortcut.
Recently I was looking at the Rhapsody Media Player. Upon initial inspection I noticed (like most media players these days) that it provided a UPnP service. This of course is used to stream media and control the music software from various clients. The whole home media network dream.
When I began looking at the UPnP code in the binary I noticed something strange. It was really uniform, and solid. This was odd as Real doesn't exactly have a great history for their software. However, I just put it in the back of my mind and carried on. After a short while I had a client that could make the proper discovery request to the Rhapsody player and retrieve its offered services.
If you are familiar with UPnP you know the requests are simply HTTP and include some valuable header information. The rhapsody header looked like so.
HTTP/1.1 200 OK
LOCATION: http://127.0.0.1:62916/
EXT:
SERVER: WINDOWS, UPnP/1.1, Intel MicroStack/1.0.1868
USN: uuid:UYKYNYWJDVTCJRJTMHJ::urn:schemas-upnp-org:service:ConnectionManager:1
CACHE-CONTROL: max-age=1800
ST: urn:schemas-upnp-org:service:ConnectionManager:1
Right off I noticed the SERVER header in particular and the string "Intel Microstack/1.0.1868". This of course reminded me of the earlier patterns I noticed in the Rhapsody binary. So I went to the best source of information on the Internet, Google. After digging through a few links I came across the "Intel Digital Home Device Code Wizard" SDK/Builder.
Downloading and unpacking this zip started to confirm some suspicions. Looking through the code I generated from the Intel SDK/Builder further confirmed everything. Real had used the Intel software to build their UPnP stack and service engines. I can confirm this by comparing the source to the binary.
Source: ILibSSDPClient.c
314: for(i=0;i<RetVal->NumIPAddress;++i)
315: {316: ILibAsyncUDPSocket_JoinMulticastGroup(RetVal->SSDPListenSocket, \
RetVal->IPAddress[i], inet_addr(UPNP_GROUP));
317: }
318:
319: buffer = (char*)malloc(105+RetVal->DeviceURNLength);
320: bufferlength = sprintf(buffer,"M-SEARCH * HTTP/1.1\r\nMX: 3\r\nST: \
%s\r\nHOST: 239.255.255.250:1900\r\nMAN: \"ssdp:discover\"\r\n\r\n", \
RetVal->DeviceURN);
Binary: rhapsody.exe
005264E5 mov edx, [ebp+var_1C]
005264E8 add edx, [ebp+arg_8]
005264EB mov byte ptr [edx], 0
005264EE mov eax, [ebp+arg_8]
005264F1 add eax, 105 <--- Key 1
005264F4 push eax
005264F5 call ds:__imp_malloc
005264FB add esp, 4
005264FE mov [ebp+buf], eax
00526501 mov ecx, [ebp+var_1C]
00526504 push ecx
00526505 push offset aMSearchHttp1_2 ; "M-SEARCH * HTTP/1.1... <--- Key 2
0052650A mov edx, [ebp+buf]
0052650D push edx
0052650E call ds:__imp_sprintf
There are many more similarities than just this line, but for brevity I exclude them. Clearly there is a link between the Intel code generator and Rhapsody binary. Further investigations proves this. With this information in hand I can use the source to augment my investigation of the UPnP code. One might even go so far as to simply look at the source from Intel, but I wouldn't rely on just that method as version skew and any added code would be missed. Having the source obviously makes things a lot easier, especially when adding structures and data types to IDA!
As previously mentioned it's easy to get into the mindset that when reversing, everything is a secret and you must start from scratch. In reality this can be a mistake, as in many cases developers use public tools and libraries to implement features. Doing this saves them precious time and allows them to quickly add a feature such as UPnP to their product.
So there it is. Our first tip. Always be thinking about the code you are looking at. Little clues can pay off big. I hope this was interesting and helpful, keep checking in every Thursday for more of our little tips and tricks.
