Log in

View Full Version : PatchMe / KeygenMe


niaren
January 8th, 2014, 09:45
Here is a crackme. It is not really mine as it is composed of 'stuff' taken from this forum.
As I'm not an experienced reverser I have no idea how difficult it is. I guess it is easy to patch but I think it will be more difficult to make a keygen (except for blabberer...doh that was my first hint )
2897

Kayaker
January 9th, 2014, 02:39
Nice one niaren! The heart of it reminds me of a certain conference RE Challenge from this Spring that was mentioned here, and which one of our members posted a nice explanation for, that should be obscure enough...

Oh yes, this looks fun and challenging
In fact, I think patching would be more difficult than keygenning...

niaren
January 9th, 2014, 03:24
hi kayaker I tried to open up the file in IDA and I was surprised to see how much code visual studio inserts into the executable. The source code (build with VS2010) consists of quite few lines of code but the exe file is huge compared to that. So VS2010 does a very good job of providing a first layer of obfuscation/obscurity The code that I know of starts at VA 0x401000 all the code executed from the entry point to that address is something visual studio is responsible fore.

I'm not sure which conference you're referring to

niaren
January 9th, 2014, 06:03
Quote:
[Originally Posted by Kayaker;95980]In fact, I think patching would be more difficult than keygenning...

I have thought about this and maybe you are indeed correct. This must mean you already know what have been done
I thought about keygenning as 'fishing' out the true code and build the keygen using that but maybe your suggestion is simpler.
I will try to see if I can find a patch later, not even sure how many bytes need to be patched.
I would like to ask you a question but will wait a couple of days just in case others want to have a look. Then I can also disclose how the exe was made.

blabberer
January 9th, 2014, 14:24
Quote:
I tried to open up the file in IDA and I was surprised to see how much code visual studio inserts into the executable.


it is called c runtime support code aptly named WinMainCrtStartUp (source code for that is available with your visual studio setup (look for crtexe.c)
it sets up console / exception / tls / exit / heap / garbage collectors / constructors / destructors /terminate handlers etc and calls WinMain or wmain which is the code you wrote and when your code returns cleans up and returns back to system it is quiet standard and for the trained eye th complete code will be neglected in one go so no obfuscation there

the byte comparison and vm like code gen is good

niaren
January 9th, 2014, 16:35
Thanks blabblerer! If you just knew how many times I have landed in this crtexe.c file whenever debugging in Visual Studio..and despite of this it has never occured to me that the code in that file is build into my application. I will definately google that file and learn more about its functionality. Then I can also find out if it is possible to stop visual studio from linking crtexe into the exe.

hehe, I think you know what is going on. Can you show a valid key
I found that this post/blog http://www.woodmann.com/forum/entry.php?167-VMprotect-VM_logic-%28in-v1-8-demo%29 seems very similar to what is going on in the crackme...that is a very strong hint!

blabberer
January 9th, 2014, 17:28
you dont have to google for that file if you have installed visual studio completely it should be available in crt\src folder
if it is not available repair install vs to install all components

Code:


C:\>dir /s /b "c:\Program Files\Microsoft Visual Studio 10.0"\crtexe.c
c:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\crtexe.c

C:\>


no you cant avoid vs from linking with that as it is necessary component without it no console support will be available
you cant use printf or stdio.h

if you do not care about console mode and are interested in Windows Mode Only
you can avoid crt code from being linked

copy paste to foo.bat and run this bat file for an example

Code:


pushd ..
@call "C:\Program Files\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x86
popd
echo #include ^<windows.h^> > test.cpp
echo int main (void) { MessageBoxA(NULL,"Hi","Hello",NULL); ExitProcess(0);}; >> test.cpp
cl test.cpp /link /SUBSYSTEM:Windows /ENTRY:main user32.lib kernel32.lib


didn't i post vm like code earlier you got your key with that reply

niaren
January 10th, 2014, 09:36
Quote:
[Originally Posted by Kayaker;95980]
In fact, I think patching would be more difficult than keygenning...


Hi kayaker, is it possible that you can tell exactly what made you first conclude that this is VM? To a trained eye I guess it is obvious but I'm just curious to learn what first got you thinking that this is VM?
Did it just 'stink' of VM from the beginning?
Was it the dispatcher loop from 40C3F2 to 40C41E that revealed the VM?
Was it some particular call flow or special instruction sequence?

It's not that easy to find a patch. Changing a jnz instruction into jz is not straight forward as their VM opcodes are of different length!
If the byte at file offset 7DDF is changed from C3->C0 any key of length 23 is accepted.

blabberer
January 10th, 2014, 15:38
can a virtual patch be called patching ?

2899

ZaiRoN
January 10th, 2014, 16:17
Quote:
In fact, I think patching would be more difficult than keygenning...

Imho, not this time. Understanding the protection routine is quite easy but a patch on the fly is really easy.

The dispatcher loop is always a good tip in a VM recognition process!
The VM is easy, it has few specific instructions and it's able to emulate x86 instructions.

Quote:
It's not that easy to find a patch. Changing a jnz instruction into jz is not straight forward as their VM opcodes are of different length!

It's possible to register the crackme with any 23 bytes length serial patching a single byte of the original exe, you only have to understand VM bytecode 0x00.

Offset 0x7DDF contains the single byte check and... good luck

rendari
January 10th, 2014, 17:11
That was a very cool minimalist VM I managed to make a 1 byte patch like ZaiRoN did and might look into keygenning if I have time after lunch.

Cheers!

-rendari

rendari
January 10th, 2014, 19:11
I might be understanding this wrong, but can you even generate a key for this that is valid ascii characters?

-rendari

Kayaker
January 10th, 2014, 22:04
Heheh blabberer, that's almost exactly the same conditional breakpoint virtual patch I came up with, except I was going to maybe change the opcode bytes to 'cmp al, al' or something rather than flipping the zero flag, just for fun.

I wasn't sure yet if the 'cmp al, bl' instruction was generated from the same location in the byte sequence beginning at 40c000, or whether there were multiple instances. If just the one, then yes I guess a 1-byte patch is possible.

What this reminded me of immediately was the Athcon 2013 RE Challenge and which Zairon nicely ripped apart

http://zairon.wordpress.com/2013/06/11/athcon-2013-re-challenge/

ZaiRoN
January 11th, 2014, 04:06
Quote:
[Originally Posted by rendari;95998]I might be understanding this wrong, but can you even generate a key for this that is valid ascii characters?

First of all try to answer this question: are you able to get the first valid char of the serial?

niaren
January 13th, 2014, 16:16
Quote:
[Originally Posted by blabberer;95994]
can a virtual patch be called patching ?

That is another very nice windbg command
bp 40c32a ".if( (wo(40c32d)==c33a) ) {bp /1 40c32f \"r @al,@bl;r zf = 1;gc\";gc} .else {gc}";

bp 40c32a
First set a conditional break on the address right before the VM is going to execute the cmp instruction

.if( (wo(40c32d)==c33a) ) .else {gc}";
only break if the instruction to be executed is cmp al,bl

"bp /1 40c32f" ;gc
if the instruction is the cmp al,bl then set a one-time BP on the instruction right after the cmp al,bl instruction and continue

r @al,@bl;r zf = 1;gc
when windbg breaks at 40c32f, print out the contents of al and bl registers and force zero flag to be set such that the keygen computation continues.

This part of the command bp /1 40c32f \"r @al,@bl;r zf = 1;gc is slightly confusing
There is a gc at the end but is that because the 'outer' BP is a conditional BP? it also works if it is just g....

blabberer, do you know if it possible to set breakpoints on all instructions from some start address to some end address, programatically in windbg? I've tried to google but have not found out if it is possible. It is possible to set BPs on multiple functions at a time by using wildcards.

niaren
January 13th, 2014, 16:28
The crackme was formed in two stages. First the raw/original crackme source file (see below) was build using VS2010 pro. The heart of the crackme is the keygen computation which was outright stolen from blabberer in this thread http://www.woodmann.com/forum/showthread.php?15414-Crack-me-help. That is the inline asm part in the source file. In the second stage the inline asm part was VM'ed by 'VMLite' (don't know its real name) as provided here http://www.woodmann.com/forum/showthread.php?15276-x86-Code-Virtualizer-Src.

I don't think it caused any problems to you but I manually renamed the added section (the one with the opcodes) .reloc

2901
(just remove the .zip part of filename)

niaren
January 13th, 2014, 16:39
Quote:
[Originally Posted by ZaiRoN;95995]
The dispatcher loop is always a good tip in a VM recognition process!

One way to maybe add in some initial confusion if the VM'ed code is not huge or time critical etc could be to unroll the dispatcher loop or maybe take it one step further by simply inlining the VM handlers (then there is no dispatcher at all)....


Quote:
[Originally Posted by ZaiRoN;95995]
It's possible to register the crackme with any 23 bytes length serial patching a single byte of the original exe, you only have to understand VM bytecode 0x00.
Offset 0x7DDF contains the single byte check and... good luck

I can see from the link that kayaker provided that you have done some serious VM reversing! I'm personally impressed that you could determine the purpose of the 00 opcode/bytecode so quickly. It took me half a day looking at the source to figure out exactly how that handler worked. for quite some time I thought that most of the instructions in that handler were garbage...

Another 'attack' point of VMs is that there must be two handlers, one handler that transform the X86 state to VM state and vice versa.

blabberer
January 13th, 2014, 19:49
Quote:
[Originally Posted by niaren;96010]

bp 40c32a
First set a conditional break on the address right before the VM is going to execute the cmp instruction

the cmp al,bl is generated on the fly so cant set bp on exact address as it will always be overwitten
so bp is set on stable address few bytes above Self modifying code


Quote:

This part of the command bp /1 40c32f \"r @al,@bl;r zf = 1;gc is slightly confusing
There is a gc at the end but is that because the 'outer' BP is a conditional BP? it also works if it is just g....


both bps are conditional breakpoints

inner bp is an one time conditional bp (there is no explicit condition but a command needs to be executed on break so it is an implicit conditional break)
commmand executed prints al,bl and sets the zf flag so needs to go from condition
outer bp checks for cmp al,bl and on success sets a bp so needs to go from condition
Quote:

blabberer, do you know if it possible to set breakpoints on all instructions from some start address to some end address, programatically in windbg? I've tried to google but have not found out if it is possible. It is possible to set BPs on multiple functions at a time by using wildcards.


what do you mean by programmatically ? writing a debugger extension ?
if yes then i think you can code something thats simply start disassembling to find the lenght of instruction
and set bps succesively on each instruction

if it is from windbg command line i havent needed it yet so havent thought of anything
now that you ask ill update this thread if i find a hack that sets bps from 401000 to 401010
like
bp 401000
bp 401005
bp 401006
bp 40100d
quit


update

here is a hack that sets breakpoints on 10 instruction / 2 instructions in winxp sp3 calc.exe
sed should be available in environment path for this to work



0:000> bl
0:000> .shell type c:\setbp.txt
[CODE]
.foreach ( place { .block { .shell -ci "u ${$arg1} ${$arg2}" sed -e 1d -e s/" ".*//g } } ) {r $t0 = place; bp @$t0 }


0:000> $$>a< c:\setbp.txt calc!WinMain l10

0:000> bl
0 e 01001f51 0001 (0001) 0:**** calc!WinMain
1 e 01001f56 0001 (0001) 0:**** calc!WinMain+0x5
2 e 01001f5b 0001 (0001) 0:**** calc!WinMain+0xa
3 e 01001f61 0001 (0001) 0:**** calc!WinMain+0x10
4 e 01001f62 0001 (0001) 0:**** calc!WinMain+0x11
5 e 01001f63 0001 (0001) 0:**** calc!WinMain+0x12
6 e 01001f64 0001 (0001) 0:**** calc!WinMain+0x13
7 e 01001f67 0001 (0001) 0:**** calc!WinMain+0x16
8 e 01001f69 0001 (0001) 0:**** calc!WinMain+0x18
9 e 01001f6a 0001 (0001) 0:**** calc!WinMain+0x19
10 e 01001f6c 0001 (0001) 0:**** calc!WinMain+0x1b
11 e 01001f6e 0001 (0001) 0:**** calc!WinMain+0x1d
12 e 01001f75 0001 (0001) 0:**** calc!WinMain+0x24
13 e 01001f7b 0001 (0001) 0:**** calc!WinMain+0x2a
14 e 01001f7d 0001 (0001) 0:**** calc!WinMain+0x2c
15 e 01001f7f 0001 (0001) 0:**** calc!WinMain+0x2e
0:000> bc *
0:000> bl
0:000> $$>a< c:\setbp.txt calc!WinMain calc!WinMain+8


0:000> bl
0 e 01001f51 0001 (0001) 0:**** calc!WinMain
1 e 01001f56 0001 (0001) 0:**** calc!WinMain+0x5

ZaiRoN
January 14th, 2014, 04:53
Quote:
[Originally Posted by niaren;96012]could be to unroll the dispatcher loop or maybe take it one step further by simply inlining the VM handlers (then there is no dispatcher at all)....

Sooner or later you will be able to recognize specific blocks because a VM is basically a sequence of code blocks. I would not use a VM to protect my program, as far as I've seen it's only able to slow down the reversing process... but it's just my personal opinion

OHPen
January 14th, 2014, 06:21
Hey,

@ZaiRoN: Come on mate! Are you serious !? ;D Nothing else than VM + obfuscation ( in VM + native ) combined with some nice crypto stuff is the way to go ( if you do not plan to include hardware in your protection ).

Hehe. Slowing down the Reverse Engineering process !? Sure, thats what its all about. Look at the Game industry, they try to save their ass from release to release by trying to complicate ( slowing down. ) the analysis of new games. And as soon as a new game is out, and the previous ( version, update ) was not cracked in the that time frame, they have been successful.

IMHO, this applies to almost every type of software i think..

Nevertheless, there is still a lot of space for improvements of common vms today. No question they improved over the years, but they are still not at their end.

@niaren: Don't listen to ZaiRoN, VMs are good !!!!!! Keep on enhancing your VM ;D

OHPen

ZaiRoN
January 14th, 2014, 06:30
@OHPen: we were talking about VM only, you put two more variables to the equation

OHPen
January 14th, 2014, 08:08
@ZaiRoN: Agree, that was unfair , but I couldn't resist, hehe.

blabberer
January 14th, 2014, 16:07
@niaren

this script will set breakpoints from some start address to some end address
the usual use it with care / no control flow / can set breakpoints in data area warnings apply

create a script xxx.txt with the following content
you must have sed (stream editor in the path for this script to work)

Code:

.foreach ( place { .block { .shell -ci "u ${$arg1} ${$arg2}" sed -e 1d -e s/" ".*//g } } ) {r $t0 = place; bp @$t0 }


the script can be run with either of the below syntax

$$>a< xxx.txt <start address> < end address>

$$>a< xxx.txt <start address> lenght

i also updated the old answer with a copy paste of output

niaren
January 16th, 2014, 16:56
Quote:
[Originally Posted by blabberer;96019]@blabbere

Thanks blabberer, you're super hardcore
I have one annoying issue with your script. It seems there is some minor difference in behavior with regards to the .shell command. Take a look at this

Code:

0:000> bl
0:000> .shell -ci "*" type c:\rce\multbp.txt
.foreach ( place { .block { .shell -ci "u ${$arg1} ${$arg2}" sed -e 1d -e s/" ".*//g } } ) {r $t0 = place; bp @$t0 }.shell: Process exited
0:000> $$>a<c:\rce\multbp.txt notepad!WinMain notepad!WinMain+8
^ Syntax error in 'r $t0 = .shell:; bp @$t0 '
0:000> bl
0 e 0028138d 0001 (0001) 0:**** notepad!WinMain
1 e 0028138f 0001 (0001) 0:**** notepad!WinMain+0x2
2 e 00281390 0001 (0001) 0:**** notepad!WinMain+0x3
3 e 00281392 0001 (0001) 0:**** notepad!WinMain+0x5
4 e 00281395 0001 (0001) 0:**** notepad!WinMain+0x8
0:000> .shell -ci "*" type c:\rce\multbp2.txt
.block { .shell -ci "u ${$arg1} ${$arg2}" sed -e 1d -e s/" ".*//g } .shell: Process exited
0:000> $$>a<c:\rce\multbp2.txt notepad!WinMain notepad!WinMain+8
0028138d
0028138f
00281390
00281392
00281395
.shell: Process exited


I have not found a way to suppress the ".shell: Process exited" message. Do you have an idea why you don't have this problem?

niaren
January 16th, 2014, 17:06
Quote:
[Originally Posted by ZaiRoN;96014]Sooner or later you will be able to recognize specific blocks because a VM is basically a sequence of code blocks. I would not use a VM to protect my program, as far as I've seen it's only able to slow down the reversing process... but it's just my personal opinion

Hi Zairon, I think I'm on the same page as you are. It should be possible to reverse the VM although it may require some serious effort. How about a VM inside a VM then? If I start thinking about VMs inside VMs I get dizzy

@PHPen just for the record, it's not my VM!

blabberer
January 16th, 2014, 22:57
no you cant avoid the .shell exited message
in fact i had to use a pseudo register to suppress misbehaviour of disabling the last breakpoint due to a . (dot representing current instruction in .shell process exited)

my initial script was just bp place
but that misbehaved and disabled the first breakpoint
so had to do r $t0 = place ; bp @$t0
this prevented the misbehaviour and the error is now harmless

these are some of the windbg quirks that you have to live with or file for a divorce

Code:

0:000> .shell type c:\\setbp.txt
.foreach ( place { .block { .shell -ci "u ${$arg1} ${$arg2}" sed -e 1d -e s/" ".*//g } } ) { bp place }
.shell: Process exited
Press ENTER to continue
<.shell waiting 1 second(s) for process>
<.shell process may need input>

0:000> $$>a< c:\\setbp.txt windbg!wmain windbg!wmain+10
Couldn't resolve error at 'shell: '
0:000> bl
0 e 010550f0 0001 (0001) 0:**** windbg!wmain
1 e 010550f2 0001 (0001) 0:**** windbg!wmain+0x2
2 e 010550f3 0001 (0001) 0:**** windbg!wmain+0x3
3 e 010550f5 0001 (0001) 0:**** windbg!wmain+0x5
4 e 010550fa 0001 (0001) 0:**** windbg!wmain+0xa
5 e 010550ff 0001 (0001) 0:**** windbg!wmain+0xf
6 d 7c90120e 0001 (0001) 0:**** ntdll!DbgBreakPoint
0:000> .shell type c:\\setbp.txt
.foreach ( place { .block { .shell -ci "u ${$arg1} ${$arg2}" sed -e 1d -e s/" ".*//g } } ) { r $t0 = place;bp place }
.shell: Process exited
Press ENTER to continue
<.shell waiting 1 second(s) for process>
<.shell process may need input>

0:000> bc *
0:000> bl
0:000> $$>a< c:\\setbp.txt windbg!wmain windbg!wmain+10
^ Syntax error in ' r $t0 = .shell:;bp .shell: '
0:000> bl
0 e 010550f0 0001 (0001) 0:**** windbg!wmain
1 e 010550f2 0001 (0001) 0:**** windbg!wmain+0x2
2 e 010550f3 0001 (0001) 0:**** windbg!wmain+0x3
3 e 010550f5 0001 (0001) 0:**** windbg!wmain+0x5
4 e 010550fa 0001 (0001) 0:**** windbg!wmain+0xa
5 e 010550ff 0001 (0001) 0:**** windbg!wmain+0xf

ZaiRoN
January 17th, 2014, 05:50
Quote:
How about a VM inside a VM then?
Well, it's what Athcon_2013's crackme does...