|  | Convincing Real Player Plus G2 to Record Enabling Record Functionality for Audio Clips
 |  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
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. 
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!) 
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.
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.
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.  
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.