just incase anyone didn't believe them already here goes the analysis (I do this sort of thing for a living) first off CherryOS.exe is what we call in the security industry "packed", that means that they have taken a compiled binary and run it through an obfuscator to make it hard to reverse engineer (or at least with hard if all you're doing is strings)...this is common for virus writers, worm writers, 31337 bot net kiddies, and on the legitimate side, game developers do this a lot...its not very common among the commercial (or free) legitimate software market (mostly because it doesn't work and doesn't do any good) so, the easiest way to defeat the packing is simply to let it start up (this one has several annoying checks for debuggers so its easiest to just attach after its loaded)... the eula for this thing says its a violation to reverse engineer it, but if you do disassemble it you find they never had the rights to license it in the first place, so I don't feel worried to put this here... if you want to follow along I downloaded a trial copy of CherryOS this morning and I got the latest version of pearpc as of this morning off of sourceforge (not from cvs, just the tarball), I am using windows XP with Interactive Disassembler (IDA)... ready...here goes: so the first thing we want to do is find some strings which are common to both, they will not in and of themselves give you the answer you're looking for but they will give us a good starting point, we will then use these to get a context on the code that uses these strings, we will then compare the functions (or in this case class methods) to see if they are similar (or in this case identical) so, example number one lets look at something in the cpu emulation code (because that is the heart of the code) direct your editor to cpu/cpu_jitc_x86/jitc.cc line 465 you will see the following small function extern "C" void FASTCALL jitc_error_program(uint32 a, uint32 b) { if (a != 0x00020000) { // Filter out trap exceptions, no need to report them ht_printf("JITC Warning: program exception: %08x %08x\n", a, b); } } first lets see if we can find the format string "JITC Warning: program exception: %08x %08x\n" somewhere in the core memory image of CherryOS now if you're using IDA attach to an already running CherryOs.exe (not to be confused with mainCherryOs.exe) and regenerate strings or do a direct string search, and search for this exact string... you will find it in the text segment located at .text:0040E890...now the fact that it exists alone is almost enough to pass summary judgment, but lets keep going so its painfully obvious... in cherryos.exe at .text:0040E8C0 you will see a reference to the format string from pearpc the disassembled function at this address looks like this (don't worry details will be explained in a bit) .text:0040E8C0 sub esp, 0Ch .text:0040E8C3 cmp eax, 20000h .text:0040E8C8 jz short loc_40E8DE .text:0040E8CA mov [esp+8], edx .text:0040E8CE mov [esp+4], eax .text:0040E8D2 mov dword ptr [esp], offset aJitcWarningPro ; "JITC Warning: program exception: %08x %"... .text:0040E8D9 call sub_491FD0 .text:0040E8DE .text:0040E8DE loc_40E8DE: ; CODE XREF: sub_40E8C0+8j .text:0040E8DE add esp, 0Ch .text:0040E8E1 retn ok, so line by line here explaining what this does .text:0040E8C0 sub esp, 0Ch this first line allocates space on the stack for three stack variables to be used as function arguments to the hf_printf function .text:0040E8C3 cmp eax, 20000h .text:0040E8C8 jz short loc_40E8DE this is checking to see if eax != 0x00020000, now normally function arguments are passed on the stack (on x86 at least), unless you're using a call convention called fastcall...I take it as hardly a coincidence that pearpc specified FASTCALL be used for this function and here it is, this line is one to one if(a != 0x00020000), then you see they jump to the return label if eax (or the first function argument) is equal to this .text:0040E8CA mov [esp+8], edx this prepares the third argument for ht_printf .text:0040E8CE mov [esp+4], eax this prepares the second arg .text:0040E8D2 mov dword ptr [esp], offset aJitcWarningPro ; "JITC Warning: program exception: %08x %"... this prepares the first arg .text:0040E8D9 call sub_491FD0 .text:0040E8DE loc_40E8DE: ; CODE XREF: sub_40E8C0+8j .text:0040E8DE add esp, 0Ch .text:0040E8E1 retn this calls what is presumable ht_printf then cleans up the stack and returns...but lets not presume, lets check... the code for ht_printf in pearpc can be found in tools/snprintf.cc line 969, it looks like this int ht_printf(const char *fmt, ...) { va_list ap; int ret; va_start(ap, fmt); ret = ht_vprintf(fmt, ap); va_end(ap); return ret; } so following the assumption that .text:0040E8D9 call sub_491FD0 is a call to ht_printf, lets check it out the assembly code at offset .text:00491FD0 is as follows: .text:00491FD0 sub esp, 0Ch .text:00491FD3 lea eax, [esp+14h] .text:00491FD7 mov [esp+4], eax .text:00491FDB mov eax, [esp+10h] .text:00491FDF mov [esp], eax .text:00491FE2 call sub_491FA0 .text:00491FE7 add esp, 0Ch .text:00491FEA retn the lea (load effective address) instruction there is the equivalent to va_start(ap, fmt), it is loading the address of the first argument to this function after the format specifier, it then takes this plus the first argument and passes it on to another function (presumably ht_vprintf, so lets check that out some turn to line 964 in the same file you will find this int ht_vprintf(const char *fmt, va_list args) { return ht_vfprintf(stdout, fmt, args); } likewise you will find in the disassembly .text:00491FA0 sub esp, 0Ch .text:00491FA3 mov eax, [esp+14h] .text:00491FA7 mov [esp+8], eax .text:00491FAB mov eax, [esp+10h] .text:00491FAF mov [esp+4], eax .text:00491FB3 mov eax, ds:dword_5C7490 .text:00491FB8 add eax, 20h .text:00491FBB mov [esp], eax .text:00491FBE call sub_491F00 .text:00491FC3 add esp, 0Ch .text:00491FC6 retn the first thing to note here is that the functions in the source code and the functions in the disassembly are directly adjacent to each other with nothing but alignment padding between them, this is generally a sure sign they were compiled from the same source file (and are part of the same object file in linking)... so looking at its content it should do little more than pass a global variable (stdout), the format string (fmt) and the varargs type to another function...and this is exactly what we find here as well...so just to be sure lets check out that global variable and make sure its stdout...a quick cross reference on it demonstrates is commonly used and always for output to the console, that sounds like stdout to me... now lets go one function deeper just incase you're not convinced, after all these have been simple functions up to this point (mostly for the readers benefit you can find as many examples as you want in here) if this code is in-fact the pearpc code we will expect the function they call at .text: 00491F00 to be ht_vfprintf, the code for which follows int ht_vfprintf(FILE *file, const char *fmt, va_list args) { #if 0 char *buf; int ret = ht_vasprintf(&buf, fmt, args); fputs(buf, file); free(buf); #else char buf[1024]; int ret = ht_vsnprintf(buf, sizeof buf, fmt, args); fputs(buf, file); #endif return ret; } and the corresponding code in cherryos.exe .text:00491F00 sub esp, 41Ch .text:00491F06 mov eax, [esp+41Ch+arg_8] .text:00491F0D mov [esp+414h], ebx .text:00491F14 lea ebx, [esp+41Ch+var_40C] .text:00491F18 mov [esp+41Ch+var_410], eax .text:00491F1C mov eax, [esp+41Ch+arg_4] .text:00491F23 mov [esp+41Ch+var_4], esi .text:00491F2A mov [esp+41Ch+var_41C], ebx .text:00491F2D mov [esp+41Ch+var_414], eax .text:00491F31 mov [esp+41Ch+var_418], 400h .text:00491F39 call sub_491DB0 .text:00491F3E mov [esp+41Ch+var_41C], ebx .text:00491F41 mov esi, eax .text:00491F43 mov eax, [esp+41Ch+arg_0] .text:00491F4A mov [esp+41Ch+var_418], eax .text:00491F4E call sub_4A3E60 .text:00491F53 mov eax, esi .text:00491F55 mov ebx, [esp+41Ch+var_8] .text:00491F5C mov esi, [esp+41Ch+var_4] .text:00491F63 add esp, 41Ch .text:00491F69 retn now remember to ignore the if 0'ed out code as it will not be compiled, if these two are identical we will expect to see a local variable of size 1024 bytes, a call to ht_vsnprintf passing the expected arguments, and then a call to fputs passing the buf and the file pointer then a return of the output of ht_vsnprintf... this is exactly what we see, allocation for 1024 bytes (400h), plus stack space for 3 function arguments, and stack space for one local 32 bit integer argument, then we see a call to a function passing arguments exactly as it does in the pearpc code then passing to a function now that second function, is at .text:004A3E60, if you look there you get a jmp to this _3bz7j9l0:005C74EC off_5C74EC dd offset msvcrt_fputs that's right, that second function call is exactly and verifiably a call to fputs()... ok, I take it you're convinced that jitc_error_program() in jitc.cc is identical to code found in cherryos.exe, but its a small function, so lets do some checking (go back to looking at cpu/cpu_jitc_x86/jitc.cc) if the code was stolen, we would expect to find jitc_error above it (you might expect to find jitc_init, but it has a different language specified because its not extern "C", so it might be there but doesn't have to be) sure enough you find exactly jitc_error (.text:0040E870) right above jitc_error_program, then you find jitc_error_msr_unsupported_bits (.text:0040E840) right above that, and so on and so forth... now, lets do something a little different, I noticed that pearpc makes use of __FILE_ from time to time for debugging purposed, lets see if we can use this to see what the source files are named in cherryos.exe do a search in IDA for ".cc" and you get the following list: cos_dec.cc x86asm.cc cos_exc.cc cos_alu.cc cos_opc.cc ide.cc debugger.cc promboot.cc prom.cc pci.cc 3c90x.c stream.cc data.cc atom.cc str.cc endianess.cc vt100.cc now, lets do a quick check of which cc files that would be built into pearpc make use of the __FILE__ macro: cpu/cpu_generic/ppc_alu.cc cpu/cpu_generic/ppc_cpu.cc cpu/cpu_generic/ppc_dec.cc cpu/cpu_generic/ppc_exc.cc cpu/cpu_generic/ppc_opc.cc cpu/cpu_jitc_x86/jitc.cc cpu/cpu_jitc_x86/ppc_alu.cc cpu/cpu_jitc_x86/ppc_cpu.cc cpu/cpu_jitc_x86/x86asm.cc debug/asm.cc debug/debugger.cc io/3c90x/3c90x.cc io/ide/ide.cc io/pci/pci.cc io/prom/fs/hfs.cc io/prom/prom.cc io/prom/promboot.cc io/prom/promdt.cc io/rtl8139/rtl8139.cc system/ui/sdl/sysdisplay.cc system/vt100.cc tools/atom.cc tools/configfile.cc tools/data.cc tools/debug.cc tools/endianess.cc tools/store.cc tools/str.cc tools/stream.cc tools/strtools.cc tools/thread.cc now, change every instance of "ppc_" for powerpc or in this case pearpc, and replace it with "cos_" for CherryOS (e.g. ppc_alu.cc becomes cos_alu.cc) and give or take some build options (some of these you cant choose together), this list is almost identical (depending on how you compile this the list IS identical)... this same trick works for asserts, confirming that even down to local variable names are the same (example given): .text:00412B11 aGjitc_nativefl db 'gJITC.nativeFloatTOP' in-fact, if you do a search for every string constant in pearpc (waaay to big to list here, but I'm sure a jury will be seeing it soon) and every string constant in CherryOs.exe (after unpacking it of course) you will find that the list is not only almost identical, but that the list is in almost exactly the same order even... so to finish up, I'm going to give a barrage of quick example from every different section in pearpc to show that it is in fact stolen directly from pearpc and renamed to cherryos.exe, then they slapped a crappy visual basic app on top of it and sold it as their own... what follows here is a large list of examples (almost one per cc file) of directly stolen code, I am only putting pointers to the stolen code in the memory space, but this should be easy to verify with your favorite win32 debugger (remember to attach after its running)...feel free to skip this part if you're already convinced configparser.cc: pearpc: line 204 void ConfigParser::loadConfig(Stream &in) cherryos.exe: .text:00404130 analysis: IDENTICAL CODE tools/atom.cc: pearpc: line 68 bool registerAtom(uint id, void *value) cherryos.exe: .text:0048CCF0 analysis: IDENTICAL CODE (right down to local variable names from ASSERT) cpu/cpu_jitc_x86/jitc.cc: line 453 extern "C" void FASTCALL jitc_error_msr_unsupported_bits(uint32 a) cherryos.exe: .text:0040E840 analysis: IDENTICAL CODE cpu/cpu_jitc_x86/ppc_dec.cc pearpc: line 37 static void ppc_opc_invalid() cherryos.exe: .text:0040ED90 analysis: IDENTICAL CODE (right down to source code file names from __FILE__ macros) tools/snprintf.cc: pearpc: line 936 int ht_vfprintf(FILE *file, const char *fmt, va_list args) cherryos.exe: .text:00491F00 analysis: IDENTICAL CODE (right down to libc function calls) io/rtl8139/rtl8139.cc: pearpc: line 742 void rtl8139_init() cherryos.exe: .text:00480230 analysis: some parts are identical, some parts appear to have been modified, but way to similar to be chance io/prom/promboot.cc: pearpc: line 988 static void read_partitions(Container &brs, bool only_bootable) cherryos.exe: .text:0044D620 analysis: IDENTICAL CODE (right down to the filename from __FILE__) io/prom/prommdt.cc: pearpc: line 1060 void prom_init_device_tree() cherryos.exe: .text:00457EC0 analysis: IDENTICAL CODE cpu/cpu_jitc_x86/x86asm.cc: pearpc: line 707 bool FASTCALL jitcFloatRegisterIsTOP(JitcFloatReg r) cherryos.exe: .text:00412B90 analysis: IDENTICAL CODE (down to filename from __FILE__ local variable names, and even code macro definition names from ASSERT) io/ide/idedevice.c: pearpc: line 91 bool IDEDevice::release() cherryos.exe: .text:0043AA00 analysis: IDENTICAL CODE debug/debugger.cc: pearpc: line 350 int Watch::toString(char *buf, int buflen) const cherryos.exe: .text:004418B0 analysis: IDENTICAL CODE Conclusion: I think I have made it clear beyond a shadow of a doubt that CherryOS.exe, shipped as the core of cherryos is nothing but a recompiled version of PearPC...it has at most minor changes, most to strip attribution, hide the theft, or remove debugging output... |