Log in

View Full Version : Using code caves for bruteforcing


bboitano
June 22nd, 2004, 11:59
Hi all,

I'm working on a several crackits and am exploring using code injection / code caves to bruteforce some of them. I've read up on the different tools that have been mentioned in the forum (topo, zeroadd and the one by Delta) and read some of the tutorials on line (Kwazy Webbit etc). Most of the online tutorials I have read all deal with a simple string compare.

I've written my own bruteforcers for some of the crackits (in VB) but my ASM coding is basically non-existant. I was wondering if there was a generic bit of ASM code that you could drop into a target that has a few options to fiddle with (i.e length, alpha-numeric) etc.

For instance one such example that I am working on - that would be an ideal subject grabs the windowtext (only the first 5 characters), then checks that it is only letters or numbers, and then proceeds to hash them and compare the resulting hash with the correct answer. (In fact, the crackit is designed to be bruteforced and I am trying to write one in VB but am struggling and would rather use the crackits own code against it so to speak).

Since I know that it is only 5 characters long, and can only be 0-9, a-z or A-Z one way to solve it would be to bruteforce it. Especially if it is a one-way hash that you can't reverse back to the original windowtext.

So can someone please either help me with my Googling skills (since I can't find anything) or help me find an appropriate section of code.

Many thanks in advance
bb

dELTA
June 22nd, 2004, 15:53
If you find it hard to write a small asm loop that increments a string for bruteforcing, I suggest you study some assembler first. Otherwise I think it would most likely be quite problematic for you to connect any code, ready-made or otherwise, to any already present hash function in the program in question in any case. Good asm skills are really handy to have in any case, so it's a good investment no matter what.

If you have some more specific questions during your attempts to do this, you are welcome to ask them here though.

bboitano
June 23rd, 2004, 10:24
dELTA - I'm sure you're right

I've download a simple target to play with from hxxp://www.woodmann.net/forum/showthread.php?t=3169 which has loads of space at the end of the file to mess around with.

Now can somone please point me in the right direction for some sample code so I have an idea where to start from to generate the characters that will be feed into validation routine (in this instance a simple CALL <JMP.&KERNEL32.lstrcmpiA>

In VB I clumsily use nested loops for a brute forcer i.e.

For a = 1 to 255
For b= 1 to 255
testpass=chr(a)+chr(b)
do stuff to check if testpass works
if good print testpass else
next b
next a

Obviously if it wanted to speed it up and only check numbers I would change the ranges to 48 to 57. Is this what I should be looking at trying to implement in ASM or is there a better way?

I was also wondering if this would be a good topic for a tutorial, since I will be approaching this with only a basic level of RE and an even more basic level of ASM understanding, I will probably ask some of the same newbie questions as others looking to do this. I realise that its not possibly the best target for a tutorial being as that we have to push both the correct answer and our generated one into the CALL making it a little redundant but I think the concept should be generally sound. Anyway - I'll start writing one up based on the RE of the crackit since its nice and simple.

Thanks again.

bb

bboitano
June 25th, 2004, 04:09
Well,


I was going to write a tutorial on how to 'code-inject' but I thought better of it due to the fact I can't really explain why I am doing what I am doing. But I can show you two examples of working code that have worked on simple crackits for me. And ask a few questions of those more experienced than I for some pointers

The first was a simple crackit that I got from Woodmans site. Since actually b/forcing the full 20chr password is a bit much for a beginner (not to mention very time consuming), I truncated it to 4 characters. And because I am a wuss!

Patching the address of the conditional jump to the Bad Serial bit with the address of 401180 (which is a nice empty bit at the end of the code) I coded this brute forcer for the four characters.

Worth noting in the orginal the password is not 4 letters long


00401180 > BB 00254000 MOV EBX,abexcm5_.00402500 ;The address I chose in memory to manipulate the pass
;In this app the proper address is 402324
00401185 . C703 30303030 MOV DWORD PTR DS:[EBX],30303030 ;Fill that address with "0000"
0040118B . C743 04 000000>MOV DWORD PTR DS:[EBX+4],0 ;make sure its terminated
00401192 . 33C0 XOR EAX,EAX ;Zero EAX [redundant now I think]
00401194 > EB 42 JMP SHORT abexcm5_.004011D8 ;Jump to checking routine - I've replicated it here but
;normally you should call to Validation_Routine
00401196 > 8043 03 01 ADD BYTE PTR DS:[EBX+3],1 ;Increment password
0040119A . 8A43 03 MOV AL,BYTE PTR DS:[EBX+3] ;Move the byte incremented to AL
0040119D . 3C 7A CMP AL,7A ;Check it compared to "}" (the next chr after "z"
0040119F . 90 NOP
004011A0 . 90 NOP
004011A1 . 90 NOP
004011A2 .^7E F0 JLE SHORT abexcm5_.00401194 ;less than "z" then continue incrementing
004011A4 . C643 03 30 MOV BYTE PTR DS:[EBX+3],30 ;if greater reset to "0"
004011A8 . 8043 02 01 ADD BYTE PTR DS:[EBX+2],1 ;increment chr before
004011AC . 8A43 02 MOV AL,BYTE PTR DS:[EBX+2] ;move newly incremented chr to AL
004011AF . 3C 7A CMP AL,7A ;Check less than "}"
004011B1 .^7E E1 JLE SHORT abexcm5_.00401194 ;if less then continue checking
004011B3 . C643 02 30 MOV BYTE PTR DS:[EBX+2],30 ;as above
004011B7 . 8043 01 01 ADD BYTE PTR DS:[EBX+1],1
004011BB . 8A43 01 MOV AL,BYTE PTR DS:[EBX+1]
004011BE . 3C 7A CMP AL,7A
004011C0 .^7E D2 JLE SHORT abexcm5_.00401194
004011C2 . C643 01 30 MOV BYTE PTR DS:[EBX+1],30
004011C6 . 8003 01 ADD BYTE PTR DS:[EBX],1
004011C9 . 90 NOP
004011CA . 8A03 MOV AL,BYTE PTR DS:[EBX]
004011CC . 3C 7A CMP AL,7A
004011CE .^7E C4 JLE SHORT abexcm5_.00401194
004011D0 .^E9 2CFFFFFF JMP abexcm5_.00401101 ;if 1st chr of 4 byte pass is equal to '{' then the
;pass doesn't lie between 0 and z so jump to error message
004011D5 90 NOP
004011D6 90 NOP
004011D7 90 NOP
004011D8 > 68 00254000 PUSH abexcm5_.00402500 ; /String2 = "" <- Our pass
004011DD . 68 00204000 PUSH abexcm5_.00402000 ; |String1 = "" <- Correct pass
004011E2 . E8 66FFFFFF CALL <JMP.&KERNEL32.lstrcmpiA> ; \lstrcmpiA
004011E7 . 83F8 00 CMP EAX,0
004011EA .^75 AA JNZ SHORT abexcm5_.00401196 ;Doesn't work therefore continue
004011EC .^E9 26FFFFFF JMP abexcm5_.00401117 ;Works - this is in fact a jump to the good boy box
;and I have patched it so the text is our pass. Perhaps
;given space create a message box with the pass
;so it could be written down and then just pass it to
;the good boy routine to continue


Improvements I can see at this point

Eliminate double jumps going from 0401194 and then back to 04011D8

Tighten up the code to remove the now redundant nops. I used them to seperate my code into segments and also they are there as a result of some tidying up.

As mentioned above use a messagebox to give you the right pass. Then pass that to the good boy routine so it can continue i.e make registry entries etc so it knows its regged. Not in this instance with this program but for others.

At this point - I have the following questions:

It looks like its fairly easy to scale this up to say 8 or more letters (obviously there is a time penalty for doing so - duh!) There may be times when we are severley limited by space so is there an more efficient method of doing this?

I need to work out a good way to preserve the state of the password. As it stands, because I have replicated the validation routine, it becomes self contained and as a result the JMP from the 'goto bad boy section' will always reset the algorithm back to '0000'. If you used this method, and the correct memory addresses, then there is a good chance that the password would be 'freed' or overwritten at some point in the validation routine.

Anybody care to give me a hand? Please remember - when you've all finished laughing at my ASM coding - that this is my first attempt to do this


Anyways - buoyed by my brilliant foray into the world of code caving I tried another crackit. This one was a crackit from theblacksheep challenge site (I heartily recommend you check it out - there are some fun things to learn and do over there) for which I had written a brute forcer in VB to crack it some time ago. Infact it was my first b/fer of any kind.

This one is nice and easy to do because it tells you it is five characters long. Handy!

So with this one (I can attach if anyone wants to see it) I've overwritten a little of the bad boy message box, not the call to it because I cannot jmp far enough away to put my code and not overwrite the good boy message

So now instead of producing the Bad Key message box it will kick you into my routine which looks the same as above nearly.


0040122F > 8005 0C304000 >ADD BYTE PTR DS:[40300C],1 ;Real password location this time - Increment it
00401236 . A0 0C304000 MOV AL,BYTE PTR DS:[40300C] ; Usual Compare stuff
0040123B . 3C 7A CMP AL,7A
0040123D . 7E 6B JLE SHORT CrackIt-.004012AA ;Again redundant double jump - should just point at
;the call to Valid_routine
0040123F . C605 0C304000 >MOV BYTE PTR DS:[40300C],41 ;For the sake of speed I have just used A-z
;Since I know there are no numbers
00401246 . 8005 0B304000 >ADD BYTE PTR DS:[40300B],1
0040124D . A0 0B304000 MOV AL,BYTE PTR DS:[40300B]
00401252 . 3C 7A CMP AL,7A
00401254 . 7E 54 JLE SHORT CrackIt-.004012AA
00401256 . C605 0B304000 >MOV BYTE PTR DS:[40300B],41
0040125D . 8005 0A304000 >ADD BYTE PTR DS:[40300A],1
00401264 . A0 0A304000 MOV AL,BYTE PTR DS:[40300A]
00401269 . 3C 7A CMP AL,7A
0040126B . 7E 3D JLE SHORT CrackIt-.004012AA
0040126D . C605 0A304000 >MOV BYTE PTR DS:[40300A],41
00401274 . 8005 09304000 >ADD BYTE PTR DS:[403009],1
0040127B . A0 09304000 MOV AL,BYTE PTR DS:[403009]
00401280 . 3C 7A CMP AL,7A
00401282 . 7E 26 JLE SHORT CrackIt-.004012AA
00401284 . C605 09304000 >MOV BYTE PTR DS:[403009],41
0040128B . 8005 08304000 >ADD BYTE PTR DS:[403008],1 ;Five letters this time
00401292 . A0 08304000 MOV AL,BYTE PTR DS:[403008]
00401297 . 3C 7A CMP AL,7A
00401299 . 7E 0F JLE SHORT CrackIt-.004012AA

Since I didn't know how much code was involved this time, there is now a huge nop gap up until 4012AA which is the jump to the call (sigh) of the is_it_valid bit.

Amazingly, doing it this way (even when allowing for 0-z) it is in the order of DAYS faster than the VB bruteforcer I wrote for the same crackit. This addition to the code can do it in minutes but my last VB bruter for this took several days (presumably for two reasons :- my programming in VB is only slightly worse than in asm :shock: and two VB had to emulate the registers which is handled here quite nicely )

Thinking more on this I also think that I should approach this in a slightly different fashion. I am concentrating in these examples (partially because I know they are of length x) changing the submitted password from 0000 to 0001 to 0002. With a little more simple coding I should be able to make the routine change the pass 0000 to 1000 to 2000 etc. I think this would give me the advantage of operating using passwords of length <x in that another check (CMP AL,00h) could be used to increment the length of the password so I start with password of length 1 and move up to length x.

Anyway, I think that is enough rambling from me for now. I would really appreciate some feedback on this and my techniques as I realise I am very new to this and am probably not doing it the best way.

Cheers all and happy RE'ing.

bb
What would Brian Boitano do?

JMI
June 25th, 2004, 04:13
He'd make a plan
And he'd follow through,
That's what Brian Boitano'd do.

Regards,

bboitano
June 25th, 2004, 05:54
Quote:
[Originally Posted by JMI]He'd make a plan
And he'd follow through,
That's what Brian Boitano'd do.

Regards,


JMI

My plan is as follows

1. Locate forum with people who can help me
2. Ask for help!
3. Show I am working on it and prepared to try things on my own
4. Ask for advice as to ways I could do things better
5. Get some pointers as to where I could be doing better
6. Ask some questions about handling the stack for another example
7. Understand what I am doing
8. Become 'Code Injection Guru'

I'm following thorugh and am up to stages 4 & 5 at the moment and hoping someone will come along and help me learn some more. Any takers ?!?!

Thanks for the laugh anyway!!

bb
What would Brian Boitano do?

Donan
June 25th, 2004, 09:22
You could always write a .dll in your favourite language and inject a call to your code. This way you dont have to be an ASM expert and you only need to reverse the crackme once

Just one link
http://www.woodmann.net/forum/showthread.php?t=4941&highlight=dll+code+injection

enjoy

bboitano
June 25th, 2004, 09:32
Thanks Donan,

I'll try and read up a little bit more on this over the weekend. I've got 101 questions right now but I imagine that a little reading will answer most of them.

Alternatively you can expect me back on Monday with 100 questions, having answered only 1!! [Most likely What Does DLL Stand For ]

But thanks for helping and have a good weekend

bb
What would Brian Boitano do?