Convincing Real Player Plus G2 to Record
Enabling Record Functionality for Audio Clips
student
Not Assigned
20 May 1999
by sNw
Courtesy of Fravia's page of reverse engineering
slightly edited
by fravia+
fra_00xx
990521
sNw
1100
NA
PC
Amazing essay! A very deep reversing study. Once more we demonstate that NOTHING can held us. sNw wanted to "analyze the various dialects and patterns of speech" for reasons of "linguistic reversing". And what does he do when he discovers that there are no right tools for doing this? He modifies, fiddles and creates them.
Note also how important is what sNw writes: "it is one thing to have the tools and quite another thing to possess a clear enough train of thought to use the right ones effectively". How true! Our strength is in our heads! In order to reverse software reversers should sit more in the shadows of a nice garden than before their screen... :-)
There are some lessons for protectors as well in here, note in particular what sNw says about SDK documentation...
Moreover "Real Player Plus G2" programmers will be able -if they want- not only to better protect, but also to improve decisively their own software after having read this great essay.
There is a crack, a crack in everything That's how the light gets in
Rating
(X)Beginner (X)Intermediate ( )Advanced ( )Expert

This essay was written for the benefit of beginners but may spark some ideas for more advanced reversers as well.
Convincing Real Player Plus G2 to Record
Enabling Record Functionality for Audio Clips
Written by sNw


Introduction

For reasons of linguistic reversing, my goal was to use some audio utility to save clips of various world broadcasts so that I could analyze the various dialects and patterns of speech. I felt that RealPlayer Plus G2 was the best tool for this goal and I was willing to pay the registration fee to have a good utility which would record online streaming clips.

Unfortunately, I discovered that very few, if any, radio stations designate their clips as "recordable", so for my purposes, the registeration appeared worthless. I soon realized that x86 had reversed RealPlayer 4.0 to add the recording functionality to every clip (see his 2 wonderful essays: x86new1.htm and x86dd2.htm). While a lot has changed with RealPlayer and x86's modifications no longer work, they gave me the idea of reversing the new RealPlayer. As a lot of functionality was added to RealPlayer Plus G2, I felt the benefits of reversing it would be well worth the effort.

Before I outline the direct method I succeeded with, I would like to mention that I spent many nights spinning my wheels with faulty plans such as using BoundsChecker, Spy++, and other message-related utils for this project. I wasted yet another night fiddling with resource editors and trapping for windows events. Finally, after many exhausted evenings, I decided to step back from the problem and take a break for a while. A week later, my mind was clear and focused and within 2 hours, I had completely solved my problem in a logical fashion. I say this because it is one thing to have the tools and quite another thing to possess a clear enough train of thought to use the right ones effectively. Sometimes you just need to step back for a while and clear the mind.

Tools required
SoftIce 3.21
W32Dasm 8.9
WinGrep (http://kili.pncl.co.uk/~huw/grep/index.html) or other pattern searching utility.
any hex editor
Real Producer G2 (optional) It can be found at www.real.com
Patience (ha!)

Target's URL/FTP
I'm sure Real Player Plus G2 is downloadable somewhere. (I registered so they mailed me the program.) Otherwise, download the demo Real Player G2 from http://www.real.com and read +TsehP's essay on creating a keygen for it.

Essay


Before beginning any reversing project, one should study the related works of peers. I read x86's essays many times, and would suggest the same of the reader. Also, check out what kind of support you can gain from the target itself or its company by reading the help files, searching web sites, etc. In my experience, this kind of information background will provide the crucial clues to an application's behavior at a critical point in the reversing process. By checking RealPlayer's website, I was able to download and study a SDK which explained in detail the file/stream formats, methods, etc. This information, while not absolutely needed, did provide a basis for a clear plan of attack.

If you will agree that at some point in time, a "recordable flag" in the form of a byte or series of bytes must be read from the incoming file or stream and processed by the RealPlayer application before any determination of "recordable" or not can be determined, then we have all the basis we need to get started. The goal is to isolate this flag check and convince RealPlayer that any given clip is "recordable", whether designated that way or not. Loosely stated, our plan will be to breakpoint at the point where the flag is initially "read", and trace through the code (using breakpoints) until we locate the place where this flag is checked by the application.

Although we really want to find the flag check for streaming audio clips, it will be much easier to find it for local files for several reasons. Using local files allows us to work at our leisure without worries of ISP timeouts and such as well as providing us with a nice initial breakpoint (bpx ReadFile). Once we have solved the recording issue for local files (functionally useless as one could just copy the file, eh?!), we will then work toward the real goal of enabling recording for streaming clips.

We can either use RealProducer G2 to create two identical files, with the single exception that one is "recordable" and the other is not and compare the files to locate the "recordable" flag byte(s), or we can read the SDK and learn that the recordable flag byte is located at the end of the "Properties" (designated by 'PROP') header. Hopefully, you will do both! The advantage of the first method is that by fiddling with the data, you will discover that the byte difference is only 1. So, by taking any non-recordable file, you can make it recordable by simply incrementing this flag byte by 1. Noting the value of this flag byte will help sound off bells in your mind as you see it float into various registers during the debugging process.

That said, let's use FileMon to discover which "reads" access this flag byte, and referencing the Win32 API, we can figure out the memory buffer for these reads and set breakpoints on the flag byte just after it is read in memory. (The alternative is to search memory for the header information and set breakpoints accordingly, but this technique is less robust and may lead to mental errors if one is not careful.) Whenever it is accessed, we will know and by tracing further we will eventually hit the flag check.

Here is a sample of FileMon's output (while playing a local .rm file with RealPlayer) with comments added:
0  Open  SUCCESS OPENEXISTING READONLY DENYWRITE		 	
1  Read	 SUCCESS Offset: 0 Length: 8192         ;Read 1st 8192 bytes (headers + more)
2  Seek	 SUCCESS Beginning Offset: 0	
3  Close SUCCESS CLOSE_FINAL	
4  Open  SUCCESS OPENEXISTING READONLY DENYWRITE 	
5  Read  SUCCESS Offset: 0 Length: 8            ;RM Header{ObjID & Size_Of_RM_Header}
6  Seek  SUCCESS Beginning Offset: 0	
7  Read	 SUCCESS Offset: 0 Length: 8            ;RM Header{ObjID & Size_Of_RM_Header}	
8  Read	 SUCCESS Offset: 8 Length: 10           ;Rest of RM Hdr{ObjVer, FileVer,NumHdrs}	
9  Seek	 SUCCESS Beginning Offset: 0	
10 Read	 SUCCESS Offset: 0 Length: 8            ;RM Header{ObjID & Size_Of_RM_Header}
11 Seek	 SUCCESS Beginning Offset: 18	
12 Read	 SUCCESS Offset: 18 Length: 8           ;Prop Header{ObjID & Size_Of_PropHdr}	
13 Read	 SUCCESS Offset: 26 Length: 42          ;Rest of Prop Hdr{ObjVer, Max_bit_rate,
                                                 Avg_bit_rate, max_pckt_size, avg_pckt_size, 
                                                 Num_interleave, Duration(milliseconds), 
                                                 Preroll(milliseconds), indx_offset,
                                                 ata_offset, num_streams, ***flag byte***}
	

Actually, there are many more reads, but only two of them (#1 & #13 above) read in the flag byte. Depending upon the structure of the file (each file has several "headers", but they may be in a different order), your FileMon output may be different. Again, reading the SDK and examining the local .rm files being played will make many things clear!

The ReadFile API function is as follows:
BOOL ReadFile(HANDLE hFile,                // handle of file to read
              LPVOID lpBuffer,             // pointer to buffer that receives data
              DWORD nNumberOfBytesToRead,  // number of bytes to read
              LPDWORD lpNumberOfBytesRead, // pointer to number of bytes read
              LPOVERLAPPED lpOverlapped);  // pointer to structure for data

Simply setting "bpx ReadFile" and playing the local file again will automatically pop SoftIce at the first target read. Note the memory offset of the lpBuffer (do a "d *(ss:esp+8)" and jot down the address, remembering to account for the backwards- looking way the number appears in memory.) In looking at the memory buffer, it should be easy to spot the flag byte. Set a breakpoint on this memory location (bpm ds:offset rw). Repeat the same method for the other target read. (To get there quickly, you could change "bpx ReadFile" to "bpx ReadFile if *(ss:esp+C)==2C" or something similar. Otherwise, just skip the intermediate reads.)

Once the appropriate "bpm" is set for this read, you can disable the ReadFile breakpoint and whenever SoftIce pops on the memory breakpoints, follow the code a little to see what is happening. If the flag byte is copied elsewhere in memory, set a breakpoint there as well. Eventually, you are sure to find this code in PNEN3260.DLL:

(There is nothing magic to finding this code, just noticing interesting things such as 2Ch = 44d = offset of flag byte within Properties header, might pique your curiosity. When suspicious, always examine the register values, memory values, etc. A "d esp+2C" here would have revealed the flag byte value you noted earlier. Actually, the "and ???, 1" caught my eye.)
:62108F04 8B4C242C  mov ecx, dword ptr[esp+2C]  ;Move flag byte into ecx
:62108F08 83E101    and ecx, 1                  ;Mask for bit 1 (recordable bit)

The trick here is knowing that within the flag byte, bit 1 is the recordable bit. You will know this if you have read the documentation or x86's essays, as this important information is clearly outlined. If you are currently playing a non-recordable clip, change ecx value to 1 by "r ecx=1", disable all breakpoints, and continue execution to discover that you can now record. Terrific! It is now time to solve the problem for streaming clips.

If you check out the deadlisting of PNEN3260.DLL, and look at the code instructions surrounding offset 62108F04 (the above lines of code), you will discover a string reference to "Flags". According to the documentation, the header values are stored in memory with associated tags, so it makes sense that our flag byte would be saved with the tag, "Flags". Not only does this reaffirm our success in locating the flag check, it may also lead us to the final goal of finding the flag check for the streaming clips. From reading x86's essays and knowing a little of the history of RealPlayer, we can reasonably assume that the flag check for streaming clips will also be found in PNEN3260.DLL. The next logical step is to search the deadlisting for other occurrences of "Flags". Sure enough, this yields another location, very similar to the code we found above. However, if you set a "bpx" on this code offset, SoftIce will never pop as it appears this code is not being used. Well, at least Zen-wise, I think we are on the right track. Rather than set a series of breakpoints (where would you start, anyway?) and spend hours online debugging, let's think about the success we've already had and see if we can apply this knowledge to finding the solution in the deadlisting.

Since we know that multiple flag values exist in a single byte and that the "and" instruction has *already* been used in the previous flag check, then now is the time to pull out a file search utility (IMO, better for sifting through a large number of lines than the old "Find"- "Find Next" method.) and search the deadlisting for lines with "and ???, 00000001". (BTW, I feel that a file searching utility, such as WinGrep, can be used to much advantage in searching for patterns in a directory of PE dumps, binary files, etc. For example, if we had the idea to search all RealPlayer executables and DLLs for "Flags", then we would have immediately found our first flag check in less than a minute. Don't underestimate the power of this technique!)

Anyway, the "and" search returns about a dozen lines. Our plan will be to "bpx" on each of these offsets, and then play a streaming clip with RealPlayer, hoping for a SoftIce pop or two which may lead to the flag check we are seeking. Since our live debugging will now be involving live data streams from the Internet, taking too much time in SoftIce will time out our connection. Rather than type each of these breakpoints in "on the fly" and risk typo errors or timeouts, why not take your time and add them to a hotkey via the WinIce.Dat file. I added the following lines to my file (3 lines, 4 breakpoints to a line) and rebooted:
CF3="bpx cs:...; bpx cs:...;...;"
CF4="bpx cs:...; bpx cs:...;...;", etc.

Then I set a breakpoint such as "bpx ReadFile" and played a clip. When SoftIce popped, I got rid of my "bpx Readfile" or whatever, and quickly pressed Ctrl-F3, Ctrl-F4, and Ctrl-F5 to set my 12 breakpoints.

Once you have set these breakpoints and continued execution, you will find that SoftIce only pops for 3 or 4 of the breakpoints, and of these, only two appear to "make sense". (It doesn't "make sense" if the same breakpoint pops several times in the loading or playing of a single clip.) To save yourself some aggravation, disable all other breakpoints. Re-play the streaming clip, and check each of the two breakpoints (one per run!) by forcing the "and" condition to return a 1 (use "r edx=1", or whatever is necessary). One of these breakpoints will cause your machine to crash and die (just kidding). Seriously, one of these breakpoints will work! For me, it was "bpx cs:62123BFB". The corresponding code in the deadlisting is:
:62123BF8 8A5030  mov dl, byte ptr[eax+30]  ;Move flag byte (or recordable byte) into dl
:62123BFB 83E201  and edx, 1                ;Recordable? (1=yes, 0=no)

So, if we change "mov dl, byte ptr[eax+30]" to "mov dl, 1", our problem will be solved. Hex edit PNEN3260.DLL, search for "8A503083" and replace with "B2019083" to patch Real Player Plus G2.

(For those who are not sure how to figure out "B201" = "mov dl, 1", set a "bpx ReadFile" or other breakpoint and play another clip. When SoftIce pops, F12 until you see a bunch of "nop" lines after a function return. Use "a cs:nop-offset" to add some code and see what develops when you type "mov dl, 1".)

Finally, I would like to point out that I have no idea what eax+30 holds in the above code. It could either be the flag byte or perhaps a recordable flag. I don't know and I don't care, either. Nor do I care how the code got to this point or where it goes from here. See, by searching for the check itself ("and ???, 00000001"), we've eliminated possible hours of weaving through the code and possibly being temporarily thwarted by false checks or thrown by other anti-debugging tricks.

Final Notes
The audio tests I've checked work perfectly, though I've only tested about a dozen online radio stations. So, I'm not guaranteeing success with everything, but it looks good so far. If recording video clips interests you, it may or may not work. If not, perhaps trying a different one of those "and" breakpoints will yield the answer.

Since I've enabled this record feature, I've enjoyed the ability to record clips "on the spot", as I hear them. This is a big plus over using a utility like XFileGet to download clips. Also, Real Player Plus G2 does an excellant job of buffering and recording only the music, not the blank spots. The playback is smooth and I am finally a happy registered customer.

Ob Duh
I wont even bother explaining you that you should BUY this target program if you intend to use it for a longer period than the allowed one. Should you want to STEAL this software instead, you don't need to crack its protection scheme at all: you'll find it on most Warez sites, complete and already regged, farewell, don't come back.

You are deep inside fravia's page of reverse engineering, choose your way out:


redhomepage redlinks redsearch_forms red+ORC redhow to protect redacademy database
redreality cracking redhow to search redjava-script wars
redtools redanonymity academy redcocktails redantismut CGI-scripts redmail_fravia+
redIs reverse engineering legal?