January 2000
"PictureAgent v2.7c2"
( 'Checking 51 known names' )
Win Code Reversing
by The Snake
Code Reversing For Beginners
Program Details
Program Name: Pa27.zip
Program Type: Group-news pics retriever
Program Location: Here
Program Size: 2.7MB
Tools Used:
 Softice V4.0 - Win'95 Debugger
W32Dasm V8.93 - Win'95 Dissembler
Easy (x )  Medium ()  Hard ( )  Pro ( )

PictureAgent v2.7c2
( 'Checking 51 known names'  )
Written by The Snake

The author of  PictureAgent v2.7c2 says :

PictureAgent is quite simply the best tool for downloading pictures from
the USENET newsgroups automatically. Select the groups to scan and
PictureAgent does the rest. As each picture is selected, it is downloaded
and decoded directly to disk. Depending on the speed of your
connection, and the number of picture files on your ISP's news server,
it's possible to retrieve 50 Megs or more of pictures in a several hour
session. PictureAgent requires Windows 95, 98 or NT.
About this protection system

 Seems that the Internet is full of Names/Serials for this utility. The program is
 checking for more then 50 (!!) names, and if one of them was entered, it will show
 the "invalid serial" message. But we know how to get the appropriate serial for
 our name, don't we ??

 The program saves the registration info in the c:\windows\PICTUREAGENT.INI :

The Essay

  Run the program. The registration screen will pop up at start up. This is only way to
  type in our details, there is no another registration screen within the program.
  There is no time limit for using this program.
  Type in name and serial, hit the "Register" button" and message pops up :
  "The registration information entered is invalid.".  We will go now to look for some
  hints in the deadlist that w32dasm will produce for us.
  Look for this error message in the "string data references", double click on it and
  there is only one occurrence for it. If you scroll down one page you will see the
  string for the window that shows "Registration information accepted" here it is :

 :004151A8 E803190000              Call 00416AB0
 :004151AD 8D4C2420                lea ecx, dword ptr [esp+20]
 :004151B1 E88A010000              call 00415340
 :004151B6 85C0                    test eax, eax
 :004151B8 7448                    je 00415202
 :004151BA 6A00                    push 00000000
 :004151BC 6A00                    push 00000000

 * Possible StringData Ref from Data Obj ->"Registration information
 :004151BE 68C8224200              push 004222C8

  We can see that the program will jump over this location if it will come back from
  the call at location 004151B1 and register eax will not hold value of "0".
  Now we know where we want to set our break-point in softice, on that call.
  Go again and type in your name and any Serial number you like. we want to set a
  break-point within SI. Type "ctrl + D" and SI pops up.  The program use the API
  GetWindowTextA to "read" the users info, so type 'bpx getwindowtexta", "x" and
  hit the "Ok" button. Softice breaks. We want to get pass of this API call, type "x"
  and we break again. We are now in mfc42 code, to get back to our program
  press "F10" 5 times, after the "ret" we will be back in PictureAgent code.
  Ok, Disable our previous BP ('bd 00").  Type "u 4151B1", this location will
  be at the top of the code screen, and type "bpx  4151B1", You can see that this
  line will be high-lighted, leave SI ("x"), and SI break on the call at
  location 004151B1. press "F8", this will take us inside this call, so we can see
  the code in this call :

 :00415340 6AFF                    push FFFFFFFF     ; we land here
 :00415342 68909F4100              push 00419F90
 :00415347 64A100000000            mov eax, dword ptr fs:[00000000]
 :0041534D 50                      push eax

     ----- snip  snip -----

 * Possible StringData Ref from Data Obj ->"paid copy"
 :0041538E 683C274200         push 0042273C
 :00415393 51                 push ecx          ; your name
 :00415394 FFD6               call esi          ; if entered "paid copy"
 :00415396 83C408             add esp, 00000008 ; eax will be here ffffffff
 :00415399 F7D8               neg eax           ; else it will be 00000000
 :0041539B 1BC0               sbb eax, eax
 :0041539D 40                 inc eax           ; if "paid copy" al=01
 :0041539E 84C0               test al, al       ; if not al=00
 :004153A0 0F8511060000       jne 004159B7      ; jump if al=01
 :004153A6 8B542410           mov edx, dword ptr [esp+10]

 * Possible StringData Ref from Data Obj ->"bit byter"
 :004153AA 6830274200         push 00422730
 :004153AF 52                 push edx          ; your name
 :004153B0 FFD6               call esi          ; if entered "bit byter"
 :004153B2 83C408             add esp, 00000008 ; eax will be here ffffffff
 :004153B5 F7D8               neg eax           ; else it will be 00000000
 :004153B7 1BC0               sbb eax, eax
 :004153B9 40                 inc eax           ; if "bit byter" al=01
 :004153BA 84C0               test al, al       ; if not al=00
 :004153BC 0F85F5050000       jne 004159B7      ; jump if al=01
 :004153C2 8B442410           mov eax, dword ptr [esp+10]

  This check for those names is being done another 49 time for names like :
  "tracy", "serial online!", "g-rom", "windows 95", "bob dole", Etc.
  If none of them was entered, we will come to the actual checking code :

 :0041591E 8B44242C          mov eax, dword ptr [esp+2C]   ; your name
 :00415922 33F6              xor esi, esi
 :00415924 3978F8            cmp dword ptr [eax-08], edi   ; name length
 :00415927 7E44              jle 0041596D  ; if name length= 0, jump

 * Referenced by a (U)nconditional or (C)onditional Jump at Address:
 :00415929 8A1C06            mov bl, byte ptr [esi+eax] ; char from name
 :0041592C 8BCD              mov ecx, ebp
 :0041592E 8D7E01            lea edi, dword ptr [esi+01]
 :00415931 E80A010000        call 00415A40             ; eax = 77h
 :00415936 8BD0              mov edx, eax
 :00415938 8BCD              mov ecx, ebp
 :0041593A 2BD6              sub edx, esi
 :0041593C 89542418          mov dword ptr [esp+18], edx
 :00415940 E8EB000000        call 00415A30             ; eax = 421h
 :00415945 8B542418          mov edx, dword ptr [esp+18]
 :00415949 8B742414          mov esi, dword ptr [esp+14]
 :0041594D 0FBECB            movsx ecx, bl             ; char from name
 :00415950 2BC1              sub eax, ecx
 :00415952 0FAFD0            imul edx, eax             ; edx=edx*eax
 :00415955 0FAFD7            imul edx, edi     ; edx=hex val for this char
 :00415958 8B44242C          mov eax, dword ptr [esp+2C]
 :0041595C 03F2              add esi, edx          ; esi=hex val until now
 :0041595E 89742414          mov dword ptr [esp+14], esi ; hex val keeping
 :00415962 8BF7              mov esi, edi
 :00415964 3B70F8            cmp esi, dword ptr [eax-08] ; end of name ?
 :00415967 7CC0              jl 00415929                ; jump if no
 :00415969 8B7C2414          mov edi, dword ptr [esp+14] ; real hex code

 * Referenced by a (U)nconditional or (C)onditional Jump at Address:
 :0041596D 8B442430          mov eax, dword ptr [esp+30] ; fake hex code
 :00415971 3BF8              cmp edi, eax    ;real code = fake code ?
 :00415973 757A              jne 004159EF
 :00415975 85FF              test edi, edi

 When the loop of calculating the real hex code for our name is done, it wil be
  moved to EDI at location 00415969   just type "? edi" and you'll see what code is
  for your name.

  Job done..
The Patches

  Nothing needed.

 REMEMBER, i'm doing my cracks as a hobby and challenge, so please, if you
 like this utility and want to keep using it, support the author and pay for it.
Final Notes

 My thanks and gratitude goes to:-

 The Sandman for all what he is doing for us, newbies.

 Rhayader for helping me with Reverse Code Engineering and useful tips

Essay by:   The snake
Page Created: 23rd January 2000