Gobe Productive Menus and Messages - uncrippling crippleware part one by PIrgE Target: 2.0 demo Tools: 1 - db the command line beos debbuger comes with beos 2 - reveng the beos native disassembler, thanks to zadig, get it! 3 - quickres, comes in beos development tools pkg Gobe Productive has an interesting range of protection: 1 - nag/demo strings on dialogs 2 - watermark printing of "Trial/Limited" Version printed underneath everything 3 - BUY menu (more unaesthetic than anything ) 4 - and saving is disabled: selecting save pops up a "Feature unavailable dialog" Of these the first two are trivial in the extreme (just examine the executable in a hex editor) and I will not deal with them here. If you cannot reverse them you need to do some more searching and learning before going any further with gobe. The second leads us to some interesting discoveries and the third is the most difficult and rewarding. QuickRes For my first attempts at reversing gobe i used quickres. Open up gobe in quickres and you can find all the menus which are referenced by a unique id number. If we change these numbers we can change the menu that is called, for example,exchange the BUY menu id with the Debug menu id, save the file and see what you find! Interesting as this is it does not enable us to reverse the save disabling but it does enable us to change the title BUY and the web address that it points to something more useful. Reveng and db The last protection is the save disabling. FIrst run gobe through reveng - take a good look at the Class Summary this is very useful allowing a sense of the app without having to read a whole disassembly listing. Here we find such functions as DoSave, SaveAs and HandleMessage. DoSave shows us what happens in the demo when Save is selected, SaveAs seems to imply that the saving code is still present in the executable (not always the case in which case no way to reverse) and HandleMessage is where we have to reverse. This function is where all menu selections go. Fire up db put a breakpoint at the start of the function and select some menu items from the File menu. You can trace where the File->Open, File->Revert etc go through the function. Single step through gobe and use the disasm from reveng to keep track of where you are and where you are going in the code. Now find the call to SaveAs in the reveng disasm - this is where we want to go. We want to work from SaveAs back up the function to somewhere we can patch all the way back to a menu item. It doesn't matter really which one at this stage we just want to exercise the code so we know that saving is possible Read the disasm from reveng and work out the jumps that need to be made. Save and SaveAs can be rerouted - change the destination address of the jumps remember - jump instructions are opcode then mode/offset so subtract start of next instruction from destination (in hex) then swap the bytes to get the machine code instructions Here is the disasm with notes - all offsets have been removed and you can work out the patch asm yourself Reference to function "TDoc::HandleMessage(BMessage *, TDocWindow *)" e8c1adffff call 83c40c add $0xc,%esp 84c0 test %al,%al 0f85da130000 jne 8b5500 mov 0x0(%ebp),%edx 81fa34324d73 cmp $0x734d3234,%edx 0f84c00f0000 je 0f878d010000 ja 81fa32304573 cmp $0x73453032,%edx //reroute call to force a path to SaveAs function////////////////// 0f8450110000 je //here when SaveAs or Open selected 0f87c4000000 ja 81fa434e435f cmp $0x5f434e43,%edx 0f8407040000 je 775b ja 81fa54455350 cmp $0x50534554,%edx 0f84d9110000 je 771d ja //this may get us to SaveAs // or reroute this call to force a path to SaveAs function////////////////// 81fa48434c43 cmp $0x434c4348,%edx 0f846b0d0000 je 81fa54454750 cmp $0x50474554,%edx 0f84b0110000 je e9fa110000 jmp Referenced by (conditionnal) jump(s) at Address(es): 81fa454c4954 cmp $0x54494c45,%edx 0f84c1110000 je 7711 ja //about box jumps from here 81fa45564153 cmp $0x53415645,%edx /////////////////////////////////////////////////////////////////// 0f8485050000 je //this will get us to SaveAs e9db110000 jmp ............some code.................. Referenced by (conditionnal) jump(s) at Address(es): 0017EF07 //save saveas & open come here 81fa36304d73 cmp $0x734d3036,%edx 0f84f7060000 je 7748 ja 81fa32304d73 cmp $0x734d3032,%edx //save jumps here 0f84a5020000 je //saveas jumps here 7723 ja 81fa33304573 cmp $0x73453033,%edx 0f848e100000 je 81fa31304d73 cmp $0x734d3031,%edx //jumps for Open 0f846b020000 je e936110000 jmp 8db600000000 lea 0x0(%esi),%esi Referenced by (conditionnal) jump(s) at Address(es): 0017EFEB //saveas comes here 81fa34304d73 cmp $0x734d3034,%edx 0f84a8020000 je 0f879e060000 ja e97a020000 jmp e94b0f0000 jmp .......some code,,,,,,,,,,, //end of menu selection parsing////////////////////////////////////////////////// .......some code,,,,,,,,,,, //Open///////////////////////////////////////// Referenced by (conditionnal) jump(s) at Address(es): a168f42f00 mov 0x2ff468,%eax Possible reference to object "OurApp" 50 push %eax Reference to function "TApp::GetOpenPanel(void)" e8c521feff call 83c404 add $0x4,%esp c6403001 movb $0x1,0x30(%eax) 50 push %eax e8fcffffff call 83c404 add $0x4,%esp e930100000 jmp //Saving///////////////////////////////////////////////// //save comes here//////////////////////////////////////// Referenced by (conditionnal) jump(s) at Address(es): 83c4fe add $0xfffffffe,%esp 666a00 pushw $0x0 6a00 push $0x0 56 push %esi 83c4fe add $0xfffffffe,%esp 666a00 pushw $0x0 eb0f jmp Referenced by (conditionnal) jump(s) at Address(es): //saveas comes here 83c4fe add $0xfffffffe,%esp 666a00 pushw $0x0 6a00 push $0x0 56 push %esi 83c4fe add $0xfffffffe,%esp 666a01 pushw $0x1 Referenced by (conditionnal) jump(s) at Address(es): 8b8678010000 mov 0x178(%esi),%eax 50 push %eax //DoSave calls alert box Reference to function "TDoc::DoSave(bool, TDocWindow *, long, bool)" e82c8dffff call 83c414 add $0x14,%esp e9fc0f0000 jmp .......some code,,,,,,,,,,, 83c404 add $0x4,%esp e9aa010000 jmp //past save as 8db42600000000 lea 0x0(%esi,1),%esi Referenced by (conditionnal) jump(s) at Address(es): e8fcffffff call //get here to get to save as//////////// Referenced by (conditionnal) jump(s) at Address(es): 8d5c2450 lea 0x50(%esp,1),%ebx 53 push %ebx e8fcffffff call 53 push %ebx 680d912e00 push $0x2e910d 55 push %ebp e8fcffffff call 83c410 add $0x10,%esp 85c0 test %eax,%eax 740e je //get to save as 6a02 push $0x2 53 push %ebx e980010000 jmp 0x17f68a//past save as 8db600000000 lea 0x0(%esi),%esi Referenced by (conditionnal) jump(s) at Address(es): 8d442434 lea 0x34(%esp,1),%eax 50 push %eax 6817912e00 push $0x2e9117 55 push %ebp e8fcffffff call 83c40c add $0xc,%esp 85c0 test %eax,%eax 0f8558010000 jne //get to save as 8d442430 lea 0x30(%esp,1),%eax 50 push %eax 681c912e00 push $0x2e911c 55 push %ebp e8fcffffff call 83c40c add $0xc,%esp 85c0 test %eax,%eax 7563 jne //jumps 8d5c2460 lea 0x60(%esp,1),%ebx 8b542434 mov 0x34(%esp,1),%edx 85d2 test %edx,%edx 7512 jne 53 push %ebx .......some code,,,,,,,,,,, Reference to function "TString::SetRep(TStringRep *)" e84bb01500 call 83c414 add $0x14,%esp Referenced by (conditionnal) jump(s) at Address(es): 8d542460 lea 0x60(%esp,1),%edx 83c4fe add $0xfffffffe,%esp 666a00 pushw $0x0 8b442434 mov 0x34(%esp,1),%eax 50 push %eax 56 push %esi 52 push %edx eb5f jmp //this goes to SaveAs 90 nop 8d742600 lea 0x0(%esi,1),%esi .......some code,,,,,,,,,,, //SaveAs where we want to be :) ///////////////////////////////// Referenced by (conditionnal) jump(s) at Address(es): 8d442460 lea 0x60(%esp,1),%eax 50 push %eax 8b8678010000 mov 0x178(%esi),%eax 50 push %eax Reference to function "TDoc::SaveAs(entry_ref const *, TString const &, TDocWindow *, TFileFormat const *, bool)" e8418affff call 83c418 add $0x18,%esp eb05 jmp .......some code,,,,,,,,,,, ---end disasm-------------------- Selecting the rerouted menu item will save a file called something like TEMP43543blah, the numbers at the end will be different each save so you get a kind of incremental save feature but you still need to rename the file to something useful. So there we go a first approach at re-enabling crippleware. Part Two: Fitting Functions - improving crippleware, will be about patching an asm function into gobe to open a Save As file panel so we can complete the uncrippling. any clarifications needed, comments, help to give or critiscm welcome - post on the beslashr web board. PIrgE respect to +orc, fravia+, lenny, zadig This essay is for esoteric purposes only I do not condone software piracy or stealing software