# Advanced Linux --- Lab 2 Albert Akmukhametov a.akmukhametov@innopolis.university _Note:_ In fact this assignment took much less time that it seems like. I've put information about all useful steps I've applied. ## Analyzing the binary First of all, let's just run it ![](https://i.imgur.com/cD2CYMx.png) We see that there is some license check based on our HWID. For now it's unknown what this HWID is. Let's take a look at `strace ./hack_app` until key is prompted (dynamic linkage part is ommited) ![](https://i.imgur.com/RNVNET7.png) We can see that there is attempt to check probably saved key in file attributes. Probably it's failed due to lack of that attribute. Bring on the ~~Fluggegecheimen~~ Ghidra! We see very pretty decompiled listing ![](https://i.imgur.com/gZE8Ky2.png) ## Patch that! We see after key was read from attributes into `xattrValue` and compared with pre-calculated key in `md5decode` ![](https://i.imgur.com/HgYhWpL.png) So if we make `local_24` equal 1 we can bypass licensing mechanis. To achieve that I'd like to flip condition on line 42. Hypothetically if file attributes will contain correct key, our patch will fail executeion. Really no key will be written into attributes because it happens after key prompt. ![](https://i.imgur.com/ggVf4PF.png) That is assembly of that condition ![](https://i.imgur.com/MNA8KNE.png) `EAX` contains result of `strncmp`. `JNZ` means jump if after `TEST` `ZF == 0` (i.e. `EAX & EAX != 0`). So, our goal is to avoid that jump (because it will skip writin into `local_24`). Let's just repace `JNZ` with its opposite `JZ`: 1. Put cursor on `jnz` and press Ctrl+Shift+G (i.e. Patch Instruction) 2. Replace JNZ with JZ. We see Ghidra's decompile listing changed accordingly ![](https://i.imgur.com/6UGj832.png) ![](https://i.imgur.com/WK1cf3Q.png) If we save it (File -> Export Program) and run we see it's runs like we have license: ![](https://i.imgur.com/3lJxEqy.png) ## Figure out key generation and create keygen For furher analysis I'll assign some comfortable names in Ghidra. Also for further analysis I'll refer to `__get_cpuid` [implementation from GCC](https://github.com/gcc-mirror/gcc/blob/master/gcc/config/i386/cpuid.h). `__get_cpuid` itself is wrapper over `CPUID` asm instruction. In our case `CPUID` called for leaf 1 --- information about processor and feature bits. ![](https://i.imgur.com/tDliwEV.png) We are interested in manipulations over `EAX` and `EDX`. First is about processor version, second is about processor features. In fact, we don't care about that, just something curious. If we compare actual HWID from given binary and result of CPUID, we can easily figure out that `HWID_LEFT=bytewsie_reverse(EAX)` and `HWID_RIGHT=bytewise_reverse(EDX)`. HWID: EC060800FFFB8B0F EAX: 000806ec EDX: 0f8bfbff From further listing we can figure out that `KEY=hex(reverse(MD5(HWID)))` ![](https://i.imgur.com/FZ2qCvr.png) So, technically, we obtain the formula for key generation. For my HWID `EC060800FFFB8B0F` key is `2fbd5901ce050f76c2719cac45fe6030`. Let's try it: ![](https://i.imgur.com/1HbDGTN.png) ![](https://i.imgur.com/CgBnKdH.png) Just to ensure I've uploaded `hack_app` to my another server and tryed to use keygen there: ![](https://i.imgur.com/0OczNTs.png) ![](https://i.imgur.com/4pVCqVP.png) Yeah, we purchased it, exactly. ## Create a patch I used python to find which byte were changed by Ghidra. ![](https://i.imgur.com/ViA10UJ.png) So I wrote simple python script which replaces required byte ```python orig_file = open('hack_app', 'rb') orig = orig_file.read() orig_file.close() patched = orig[:5534] + (116).to_bytes(1, 'little') + orig[5534+1:] patched_file = open('hack_app.patched', 'wb+') patched_file.write(patched) patched_file.flush() patched_file.close() ``` ![](https://i.imgur.com/BuipLEM.png)