12/2000 by Zadig. Tools needed: A disassembler: dasm or reveng. A debugger: db. Introduction: In this text I will explain you how to register Moho by changing only 1 bit! That's incredible, we have very good applications in our prefered OS but they are not protected at all. Moho is "a complete animation system for creating 2D cartoons", and believe me it is really a wonderfull soft. With it you can easily create 2D cartoon pictures or animations. You can download the demo from lostmarble's web site, or from BeBits. This demo can be used as long as you want but has several limitations: A nag screen asks you to enter a serial number. When you render or preview a project, a watermark is printed. As this text explains basic methods it is destinated to newbies or newcomers on BeOS targets. If you already reversed several apps on beos you will probably learn nothing here. I- How to register Moho: Now let's disassemble moho to find interesting symbols. We have a lot of them: - several "registration" strings. - "If you have purchased Moho, enter your registration number below to unlock ". - Class RegistrationDlog. - Class MRegistration. - Class TPrefs. That's more than we need. The class RegistrationDlog is the nag screen (what else could it be?) that asks us either to enter a serial number or start a demo session. the string "if you have purchased..." would certainly confirm that it's this window: It should be used in the constructor of the class. The MRegistration is very interesting too and especially two methods: MRegistration::Verify and Decode. That sounds very good for us don't you think? The Verify may be used to check the serial that was decoded with Decode. Finally the TPrefs may help us if the registration code is loaded with it. A this point we have several ways to continue: - Starting from the nag screen. - Strating from the "Verify" and "Decode" functions. - Finding a valid serial number. Choosing one or another is very personnal. I will start from the "verify" function because it is probably the key point of the protection (with that name it can't be used to print help!). So let's search for "Verify" it in the disassembly. There are no references to it but it calls "Decode", does some checkings and put the result in eax. Before going deeper in it, let's have a look to "Decode": It is called in 3 places one of which is very interesting: MohoWnd::OnCreate. This means that it's called as soon as we launch the app: Reference to function "TApp::Prefs(void)" xxxxxxxx: call 0xa1208 xxxxxxxx: mov %eax,%edx xxxxxxxx: lea 0xffffffec(%ebp),%eax xxxxxxxx: push %eax xxxxxxxx: mov %ebx,%eax xxxxxxxx: add $0xffefc124,%eax Possible reference to string "Registration" xxxxxxxx: push %eax xxxxxxxx: push %edx Reference to function "TPrefs::Get(char const *, char const **)" xxxxxxxx: call 0xa7ddc xxxxxxxx: add $0x10,%esp xxxxxxxx: test %al,%al xxxxxxxx: je ADDR1 xxxxxxxx: lea 0xffffffe8(%ebp),%eax xxxxxxxx: push %eax xxxxxxxx: lea 0xffffffe4(%ebp),%eax xxxxxxxx: push %eax xxxxxxxx: lea 0xffffffe0(%ebp),%eax xxxxxxxx: push %eax xxxxxxxx: lea 0xffffffdc(%ebp),%eax xxxxxxxx: push %eax xxxxxxxx: mov 0xffffffec(%ebp),%eax xxxxxxxx: push %eax Reference to function "MRegistration::Decode(char const *, unsigned long *, unsigned long *, unsigned long *, unsigned long *)" xxxxxxxx: call 0xc194c xxxxxxxx: add $0x14,%esp xxxxxxxx: cmpl $0x17e,0xffffffe0(%ebp) xxxxxxxx: jne ADDR1 xxxxxxxx: mov 0x60c(%ebx),%eax xxxxxxxx: movb $0x0,(%eax) ADDR1 : mov 0x60c(%ebx),%eax xxxxxxxx: cmpb $0x0,(%eax) xxxxxxxx: APP_START ... Show Nagscreen That's great, we won't need to look into the "Verify" function at all: All the protection is here. First we read the serial number in moho's settings files, then we check that it is correct. If it's the good one the app is launched, in the other case the nag screen is printed. Here is the same code with comments: Reference to function "TApp::Prefs(void)" xxxxxxxx: call 0xa1208 /* new TPref */ xxxxxxxx: mov %eax,%edx xxxxxxxx: lea 0xffffffec(%ebp),%eax xxxxxxxx: push %eax xxxxxxxx: mov %ebx,%eax xxxxxxxx: add $0xffefc124,%eax Possible reference to string "Registration" xxxxxxxx: push %eax xxxxxxxx: push %edx Reference to function "TPrefs::Get(char const *, char const **)" xxxxxxxx: call 0xa7ddc /* reads the "registration" key in the settings file */ xxxxxxxx: add $0x10,%esp xxxxxxxx: test %al,%al /* if the key doesn't exists */ xxxxxxxx: je ADDR1 /* continue to load app */ xxxxxxxx: lea 0xffffffe8(%ebp),%eax /* set parameter for "Decode" */ xxxxxxxx: push %eax xxxxxxxx: lea 0xffffffe4(%ebp),%eax xxxxxxxx: push %eax xxxxxxxx: lea 0xffffffe0(%ebp),%eax xxxxxxxx: push %eax xxxxxxxx: lea 0xffffffdc(%ebp),%eax xxxxxxxx: push %eax xxxxxxxx: mov 0xffffffec(%ebp),%eax xxxxxxxx: push %eax Reference to function "MRegistration::Decode(char const *, unsigned long *, unsigned long *, unsigned long *, unsigned long *)" xxxxxxxx: call 0xc194c /* "decodes" the serial number */ xxxxxxxx: add $0x14,%esp xxxxxxxx: cmpl $0x17e,0xffffffe0(%ebp) /* if code isn't correct... */ xxxxxxxx: jne ADDR1 /* continue to load app */ ADDR2 : mov 0x60c(%ebx),%eax /* get address of demo flag */ ADDR3 : movb $0x0,(%eax) /* reset demo flag */ ADDR1 : mov 0x60c(%ebx),%eax /* get address of demo flag */ xxxxxxxx: cmpb $0x0,(%eax) /* reset address of demo flag */ xxxxxxxx: je APP_START ... Show Nagscreen Once again we can continue in several ways: - After TPrefs::Get we can force the jump to APP_START. That's what I did first but it's not a good patch: The nag screen won't popup but the watermark will still be there and it will be quite hard to find where it is printed. - After TPrefs::Get we can force the jump to ADDR2. That's much better. The demo flag will be negated and moho will believe that we are registered. No more nag and no more watermark. - We use our brain and we think for 3 more seconds. Of course I choosed the 3rd solution. So what's wrong? I can hear some of you saying "We've got a working patch, we're registered, what do you want more? ". Well, it's working but today (as the other days) I am lazy and I don't want to patch so much bytes. When we are at ADDR2 the value of 0x60c(%ebx) is 1. This means that it was initialised to 1 somewhere no? Time has come to use db. Launch moho with db and put a breakpoint at ADDR3. Now get the value of eax with "dm eax", this is the address of the flag (I will call it ADDR_FLG). To find where it is initialised we will put a watchpoint on it. A watchpoint is a memory write breakpoint, this means that db will break when moho will write in ADDR_FLG. To put the watchpoint restart moho and type "watch ADDR_FLG". Then let the app run and db will break here: xxxxxxxx: mov 0x60c(%ebx),%eax xxxxxxxx: movb $0x1,(%eax) /* we found it ! */ xxxxxxxx: jmp 0x41b37 /* we break here */ We found it, just replace "movb 1,eax" with "movb 0,eax" and moho will be registered. All the protection relies on 1 bit, that's unbelievable. II- Finding the watermark In the previous part I told you that it was hard to find where is the watermark protection if you didn't see the demo flag. On the other way you will see that it is very easy when you know about this flag. In this part we will search where is the watermark and how it's coded. Of course we don't have to do it (Moho is already registered) but we are here to study protections, so let's study... To find the watermark we must find where the code reads the demo flag. In the disassembly we saw that the flag was at address "0x60c + ebx". The question is how can we find where moho access to this flag? We can't use watchpoints because they only break on memory write. So we will use the dead listing but how? If you're a newbie you probably think "we just have to search for 0x60c(%ebx)", and if you're more familiar with assembler you will say "it's not that easy because ebx is a register". Because ebx is a register its value may be different in different parts of the code so that 0x60C+ebx may not refer to the same address, right? Wrong! It's wrong for 1 reason: BeOS executables are heavily based on ELF, and in an ELF file ebx register is reserved and ALWAYS contains the start address of the ".got" section. That's why on the begining of each function you can see "pop ebx" and "add xxx,ebx". What I want to say here is that we can search for "0x60c(%ebx)". All references we will find will be to our flag. We've got several ones and especialy in MohoRenderMgr::Tick(void) and MeshLayer::ExportFlash. Lets begin with MohoRenderMgr::Tick(void): xxxxxxxx: mov 0x60c(%ebx),%eax /* reads the demo flag */ xxxxxxxx: cmpb $0x0,(%eax) /* if it is 0 ... */ xxxxxxxx: je ADDR_RENDER /* ... continue render */ xxxxxxxx: mov 0x8(%ebp),%edx /* else ... */ xxxxxxxx: mov 0x4(%edx),%eax xxxxxxxx: push %eax Reference to function "MImage::operator Mt_image const *(void) const" xxxxxxxx: call 0xaa88c /* create new image */ xxxxxxxx: push %eax xxxxxxxx: mov 0x7f4(%ebx),%eax xxxxxxxx: push %eax Reference to function "MImgOps::TileImageAlpha(Mt_image const *, Mt_image const*)" xxxxxxxx: call 0xb724c /* put it on the background */ xxxxxxxx: add $0xc,%esp ADDR_RENDER: mov 0x8(%ebp),%edi /* render the scene */ This function is the one that renders the scene. As you can see no specific function is called here. No "PrintWatermark" or any stuff of this kind. That's why it should be very hard to find without the demo flag (but very easy with it:-). It may have been a good protection if lostmarble had thought a little bit more on it. As the ExportFlash protection is similar to this one I won't explain it. III- Conclusion To protect it better lostmarble should really change their registration method. Once again we don't have to know anything about the key generation to get registered. Will editors read the "how to protect better" tuts on fravia's site one day? Remember: This text is for educational purpose only. If you use this soft, buy it. See you later, Zadig.