Author | Message | Time |
---|---|---|
tA-Kane | I'm currently disassembling an anti-hack program that is protected using (I assume) SVKP. While I believe I am making progress, I do believe I've hit a small stump. First, let me explain what I've noticed this thing doing so far. At the program launch, it decodes a few strings containing pathnames to known debugger files and attempts to open those files. If none were successfully opened, it proceeds to the next step. From here on out, a lot of jumps are used to skip junk bytes in the code, and numerous (though easily identifiable) useless jumps which are assumably throwing a debugger or disassembler off. What it does next is copy some what I thought was junk data to the stack. Then to my astonishment, it jumped to the stack. With that in mind, it's obviously trying to throw disassemblers off there ... since the instructions are embedded into a number of mov instructions (and in fact are actually decoded using various xors before being pushed to the stack), a disassembler would not be able to disassemble those instructions without a *lot* of help. In any case, what that appears to be doing is decrypting a small amount of code inside the data section, and then jumps there. That also decrypts a larger amount of code in the data section and then jumps to it, which also decrypts more code. The sixth or seventh time doing this, it references the origional code. I'm not totally sure what to do, and I was wondering (for those of you whom have disassembly knowledge). I have a vague idea, but I don't think it'd be good in terms of time taken. Thoughts? | May 9, 2005, 8:13 AM |
Adron | I'm not familiar with SVKP. Apart from that, yes, it sounds like it's decrypting code in multiple layers. I have seen that before, and either you keep going through the decryption rounds, perhaps seeing a pattern that you can apply to do the whole thing yourself, or you let it run to conclusion in a safe environment and then halt it and take the resulting code from in memory. If the protection wasn't designed into the program from the start, you can most likely just find the right spot to break, and then you'll have all of the program available, decrypted, in memory. Such protections or exe packers typically do run the decryption code on the stack, and the decryption code decrypts/unpacks data from a data section, to memory starting at 401000, the regular exe code loading address. It sounds like that may be what you're seeing. | May 9, 2005, 11:00 AM |
tA-Kane | SVKP information: http://www.anticracking.sk/products_svkp.html SVKP claims that it can encrypt individual functions, which I know to be possible. If that's the case, then waiting for it to finish decoding the layers of code before dumping memory might not provide all of the code of the program, which while it could provide some would still be annoying. I'll go through the decryption code again and look for 401000, but I do not recall initially seeing anything being sent to 401xxx. | May 9, 2005, 11:16 PM |
Adron | Well, could be written to 400000 as well. Have you seen any end to the loops running code on stack? | May 10, 2005, 1:11 AM |
tA-Kane | Yes, in fact I thought I had stated such before, but maybe it wasn't clear. Let me highlight it for you. [quote author=tA-Kane link=topic=11531.msg111650#msg111650 date=1115626423]it jumped to the stack. ... appears to be ... decrypting a small amount of code inside the data section, and then jumps there.[/quote] (two hours later) I seem to have found a tutorial (I hope) of breaking (I hope) SVKP's algorithms, although it is in Russian (ugh! No Google Language Tools in this case!). Does anyone here happen to read Russian? It'd be nice if I could get this translated: http://bioworm.ahteam.org/reversing/svkp.html | May 10, 2005, 6:08 AM |
Adron | Oh, ok, so from then on it runs in the data segment. Have you seen any end to the loops decrypting/running code in the data segment? | May 10, 2005, 10:53 AM |
KkBlazekK | http://babelfish.altavista.com Can translate the page. | May 10, 2005, 7:55 PM |
tA-Kane | [quote author=Adron link=topic=11531.msg111847#msg111847 date=1115722386] Oh, ok, so from then on it runs in the data segment. Have you seen any end to the loops decrypting/running code in the data segment? [/quote]Not myself. But apparently there is. I set a breakpoint to executing 401000 just as the screenshot on that page had suggested, and the program halted after a while. I'm trying to figure out what to do next. There are 7 NOPs followed by some various instructions. According to that document, the first NOP is where the program's entrypoint is. It was hard understanding what it was saying to do, but adding the two push statements pushing the two values from the stack seems to fit the NOPs well (push 60; push 4182c8). I *hope* that's what he meant to do. I'm not sure what he means with those last few instructions before dumping, though. Are they something I need to look for? Are they something I need to add or change somewhere? I'm especially confused when he's talking about "mov eax,XXXXXXXX". Thanks for reminding me of babelfish btw, Blaze. | May 11, 2005, 12:58 AM |
tA-Kane | I seem to be able to all but get a dump of the decrypted code. It appears that there's 6 imports which point to code within a codebase of 0x00EA0000. When trying to fix the stack using ImpRec, it does not even see a DLL at such a codebase, so it's either hidden somehow or is created by the program itself. When deleting those imports and running (yes, not a wise idea, but oh well), the dumped program crashes at launch when attempting to access that same codebase. Looking at the memory maps of the origional and the dumped application, there's a few differences: One obvious one is that WS2HELP and WS2_32 are loaded. Another notsoobvious difference is that there are two extra unnamed memory sections, 0x00EA0000 - 0x00EB6000 and 0x00EC0000 - 0x00EC3000. Since jumps are occuring to 0x00EAxxxx, I'd venture a guess that 0x00EA0000 contains code and 0x00EC0000 contains data for that code. The big questions that I have now would be: 1) Would it be dangerous to modify a part of the real program's code (whether in code section or in the data section and then set the modified data to zero when complete) to load WS2_32 and WS2HELP? 2) How would I dump the two unknown sections and then load them at the beginning of the dumped code? Any help would be appreciated. | May 13, 2005, 9:08 AM |
Adron | Check the contents of those sections manually and see if there are any strings that give you clues to what they are. Dangerous to modify the program? Not really, especially if you know what you're doing ;) | May 13, 2005, 12:54 PM |
tA-Kane | Nothing in the second (smaller) section. The first contains few strings, and none of which I consider real value: [quote]This function is not implemented in UNREGISTERED version! Please register it![/quote][quote]UNREGISTERED VERSION![/quote][quote]ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/.[/quote][quote]Service Pack 2[/quote][quote]*file path filtered*[/quote][quote]*directory path filtered*[/quote][quote]game.exe[/quote] The two strings just below the alphabet are a path to the currently running EXE (eg, the debugged EXE) and the directory containing the currently running EXE, respectively. Besides stepping through various code and watching it manually, is there any way that I could see at what point these two sections are added to the EXE's memory map? Maybe some Win32 API calls that I could breakpoint? Then I should be able to modify the resulting executable to mimic it (or even call it again... yet for the first time... as a different exe). | May 15, 2005, 5:30 AM |
Adron | [quote author=tA-Kane link=topic=11531.msg112505#msg112505 date=1116135023] Besides stepping through various code and watching it manually, is there any way that I could see at what point these two sections are added to the EXE's memory map? Maybe some Win32 API calls that I could breakpoint? Then I should be able to modify the resulting executable to mimic it (or even call it again... yet for the first time... as a different exe). [/quote] I'd suggest looking at VirtualAlloc first, but, you may have to check all memory allocation calls, because it could be any. | May 15, 2005, 12:27 PM |
Kp | IIRC, windbg is able to do API logging, so you could run it once to get a listing of what calls were made, then breakpoint on the most likely memory-allocating candidate (and run a second time with the breakpoint). I think it even saves the return value, which might let you find the call on the first try. | May 15, 2005, 2:44 PM |
tA-Kane | Hmm, I was screwing around and found a reference to WS2_32.send, so I breakpointed the beginning of the function, looks like I've accidently found the function that sends data to the server-side part of the anti-hack process BEFORE the data gets encrypted, which is one important step towards writing a third party client. So now I wonder, would it be more prudent to keep doing what I was doing before (trying to get a working dump of the decrypted exe), or should I try to see what I can do from this function alone? I'm 90% confident I could trace the program backwards from here... but I'm not so sure about locating where the receiving end of the socket is at... though I'm sure I'll find it with time (after all, if its a nonoverlapped socket, it's gotta be somewhere upper and back down in the calling path... and if it's overlapped, the receiving function needs to be set somewhere...). Hmmm... | May 19, 2005, 5:27 PM |
iNsAnE-MS | Holy crap, you guys are crazy. I wish I could do something awesome like you guys do with this. | May 19, 2005, 7:35 PM |
Kp | [quote author=tA-Kane link=topic=11531.msg113005#msg113005 date=1116523650] Hmm, I was screwing around and found a reference to WS2_32.send, so I breakpointed the beginning of the function, looks like I've accidently found the function that sends data to the server-side part of the anti-hack process BEFORE the data gets encrypted, which is one important step towards writing a third party client. I'm 90% confident I could trace the program backwards from here... but I'm not so sure about locating where the receiving end of the socket is at... though I'm sure I'll find it with time (after all, if its a nonoverlapped socket, it's gotta be somewhere upper and back down in the calling path... and if it's overlapped, the receiving function needs to be set somewhere...). Hmmm...[/quote] This may seem a bit obvious, but have you considered just setting a breakpoint on recv itself? [u]bp ws2_32!recv[/u] should do it. That'll break to windbg when recv gets called, which should let you get a backtrack into non-encrypted code. Other functions to consider breaking on: kernel32!ReadFile, kernel32!ReadFileEx, ws2_32!recvfrom, ws2_32!recvmsg. | May 19, 2005, 9:32 PM |