Recently I have been learning the MIPS assembly due to assignments and so one of the first tasks was to implement the bubble sort algorithm.
It doesn't use tables to store the array but takes the integers as input interactivly and is not limited to 5 inputs because it uses the stack so useful for anyone who is learning MIPS
Here it is for any of you who may be interested...
##########################################
##### BUBBLE SORT --> mah165 ####
##########################################
.data
.align 4
banner: .asciiz "++++++++++++++++++++++++++++++++++\n"
banner1: .asciiz "| MIPS BUBBLE SORT V0.1 |\n"
banner2: .asciiz "++++++++++++++++++++++++++++++++++\n"
promptIntList: .asciiz "[Integer] (0=exit) >>> "
crlf: .asciiz "\n"
space: .asciiz " "
sortedLabel: .asciiz "Sorted array: "
busyLabel: .asciiz "Swapping ...\n"
.text
.globl main
main:
add $fp, $zero, $sp; #set frame pointer
move $s1, $ra # store return address
li $v0, 4; # opcode for print_string
la $a0, banner; # arg for print_string
syscall; # syscall
la $a0, banner1; # next arg
syscall; # syscall
la $a0, banner2; # next arg
syscall; # syscall
li $s0,0; # number of integers initialize
PROMPTINT:
li $v0, 4; # opcode for print_string
la $a0, promptIntList; # argument for print_string
syscall; # call print_string
li $v0, 5; # opcode for read_int
syscall; # call read_int
beq $v0,0,bubblesort;
addi $sp,$sp,-4; # decrement stack -4
sw $v0,0($sp); # store user input onto the stack
addi $s0, $s0, 4; # store stack counter in s0
j PROMPTINT; # jump back to PROMPTINT;
bubblesort:
beq $s0,0,EXIT; # check if number of ints*4 is > 0
move $t0,$sp; # outerloop counter
add $t4,$sp,$s0; # outerloop termination
addi $t4,$t4,-4;
bubbleLoop1:
move $t1,$sp; # innerloop counter
sub $t6,$t0,$sp; # inner loop end condition
sub $t6,$t4,$t6;
bubbleLoop2:
lw $t2,0($t1); # get first int
lw $t3,4($t1); # get second int
slt $t5,$t2,$t3; # if n[0] < n[+1] set t5 = 1
bne $t5,$zero,swapFalse;# if $t5 == 0 !swap ... else swap
move $t5,$t2; # move $t2 into $t5
move $t2,$t3; # move $t3 into $t2
move $t3,$t5; # move $t5 into $t3
sw $t2,0($t1); # restore back to stack swapped
sw $t3,4($t1); # ..............................
swapFalse:
addi $t1,$t1,4; # increment to next int
bne $t1,$t6,bubbleLoop2; # if not end then back to loop
li $v0,4
la $a0, busyLabel; # print a status
syscall; # call the print
addi $t0,$t0,4; # increment outer loop counter
bne $t0,$t4,bubbleLoop1; # if !=$t0 back to loop else:
li $v0,4; # print:
la $a0,sortedLabel; # sorted array...
syscall; # call the sys for print label
jal printArrayList; # now print sorted array
j EXIT; # then exit cleanly
printArrayList:
move $t5,$sp; # print counter
add $t2,$s0,$t5; # end condition
printArrayLoop:
li $v0, 1; # opcode print int
lw $a0,0($t5); # arg for print int
syscall; # call
li $v0,4; # print string
la $a0,space; # space
syscall; # call
addi $t5,$t5,4; # next int
bne $t5,$t2,printArrayLoop; # if int left then print next
li $v0,4; # print code
la $a0,crlf; # new line
syscall; # call
jr $ra; # return to caller
EXIT:
move $ra,$s1
jr $ra
Thursday 7 February 2013
Sunday 6 January 2013
Reverse Engineering a password protected file + ptrace() Anti-Debugging bypass.
So I have run into a lot of anti-debugging techniques over the years and wanted to show how to bypass one of the simpler ones to start off with. Maybe in another post I will show how to bypass more "difficult" techniques if anyone requests it.
hmmm... Prerequisites:
* Linux OS
* gdb
* objdump
* x86 Assembly knoweledge
* Reverse Engineering basics
gdb and objdump should be installed on your Linux OS by standard, however if they are not you can install them from your favourite package manager.
Yes you will need perseverance if your a beginner to this because things can get tricky,
and basic knowledge of Assembly and reverse engineering binaries.
So lets get to it!
Firstly download the binary file from --> here <--
And lets begin some static analysis:
root@fedvm /pentest/reverseEngineering # file anti-Dbg.bin
anti-Dbg.bin: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.9, not stripped
So its an ELF 32-bit executable and its symbols have not been stripped which is always good for debugging.
lets run the file:
root@fedvm /pentest/reverseEngineering # ./anti-Dbg.bin
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|| Welcome to an anti debug challenge !!!!! ||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Password : password?
Wrong password.
So it gives us a password prompt but we have know way of possibly knowing what it could be. So lets get all static strings from the file, maybe it has been stored in a variable? If you run the command:
root@fedvm /pentest/reverseEngineering # cat anti-Dbg.bin | strings
You can see there is a lot of junk but among those strings you can find the text displayed at run time and password prompt with a simple '| grep "welcome" ' or ' | grep "password" '
However any other strings that look like they could be passwords are not. So next step...debugging the application to get the password.
root@fedvm /pentest/reverseEngineering # gdb -q anti-Dbg.bin
Reading symbols from /pentest/reverseEngineering/anti-Dbg.bin...(no debugging symbols found)...done.
(gdb) r
Starting program: /pentest/reverseEngineering/anti-Dbg.bin
You Lose! Debuggering!....
[Inferior 1 (process 3731) exited with code 01]
(gdb)
So the program has detected us debugging and doesn't even let us start to make any progress... unless we could stop the program at the beginning of execution? Before the anti-debugging has a chance to kick in? If its that type of AD technique... lets try it. Add a breakpoint to main.
(gdb) b *main
Breakpoint 1 at 0x80483f0
(gdb) r
Starting program: /pentest/reverseEngineering/anti-Dbg.bin
Breakpoint 1, 0x080483f0 in main ()
So we have added a breakpoint to main and it has now paused execution. (note. sometimes b *main wouldnt work because of symbols not being included during compilation or if the program utilizes an in-memory encryption-decryption algorithm, so the next step will explain how to set a breakpoint at the start of a program regardless of this issue).
Now we need analyze the x86 ASM code and step through the program avoiding the anti-debugging techniques. We do this using objdump.
root@fedvm /pentest/reverseEngineering # objdump -D anti-Dbg.bin > antiDebugObjDump
Now navigate inside this file to the line which says 080483f0 <main>:
(your address may be different to mine)
Here is the beginning of the program and the address is what you could use to also set the breakpoint on main if *main doesn't work...:
(gdb) b *0x080483f0
Now lets analyze the Assembly code whilst debugging the application, to bypass the anti-debugging techniques in place.
Firstly after the initial stack setup I see these instructions which look interesting:
8048401: c7 45 f4 88 28 0c 08 movl $0x80c2888,-0xc(%ebp)
So here a value located at -0xc(%ebp) is being loaded into the address 0x80c2888. I wonder what this is? Lets set a breakpoint here for later.
(gdb) b *0x08048401
Breakpoint 2 at 0x8048401
Next:
8048408: 6a 00 push $0x0
804840a: 6a 01 push $0x1
804840c: 6a 00 push $0x0
804840e: 6a 00 push $0x0
8048410: e8 5b 06 01 00 call 8058a70 <ptrace>
What we have here is arguments being pushed onto the stack for the function call ptrace at 0x08048410. If you already have C knowledge you may have seen this ptrace() function call before. You can use this function to check if any other processes attach to the current process which made the ptrace call. This is most likely how the ptrace is working.
lets continue:
(gdb) c
Continuing.
Breakpoint 3, 0x08048401 in main ()
(gdb) si
0x08048408 in main ()
//We are now at the instruction one after the the movl instruction which moved a value into 0x80c2888. Lets see what that value was:
(gdb) x/8s 0x80c2888
0x80c2888: "ksuiealohgy"
0x80c2894: "You Lose! Debuggering!...."
0x80c28af: ""
0x80c28b0: '+' <repeats 60 times>
0x80c28ed: ""
0x80c28ee: ""
0x80c28ef: ""
0x80c28f0: "|| Welcome to an anti debug challenge !!!!! ||"
So it saved the string "ksuiealohgy". hmmm lets ignore it for now but keep it in mind...
Also below we see other strings that we have encountered.
Before we go any further lets put a breakpoint on the next important instruction:
804841a: 79 1a jns 8048436 <main+0x46>
(gdb) b *0x0804841a
and continue using "c"...
(gdb) c
Continuing.
Breakpoint 4, 0x0804841a in main ()
We are now at the JNS instruction. This means Jump Short if Not zero and the value it is interested in is the SF (Sign flag) located in the FLAGS register. lets see what this value is:
(gdb) p $eflags
$1 = [ PF SF IF ]
It seems the SF flag is set so the jump will not be made so lets see what happens now when we continue:
804841c: 83 ec 0c sub $0xc,%esp
804841f: 68 94 28 0c 08 push $0x80c2894 ; what is this string being pushed onto the stack? it is what is going to be used as an argument in the next function puts().
8048424: e8 a7 0e 00 00 call 80492d0 <_IO_puts>
8048429: 83 c4 10 add $0x10,%esp
804842c: b8 01 00 00 00 mov $0x1,%eax
8048431: e9 c3 00 00 00 jmp 80484f9 <_notng+0x62>
8048436: 83 ec 0c sub $0xc,%esp
(gdb) si //step
0x0804841c in main ()
(gdb) si //step
0x0804841f in main ()
(gdb) si //step
0x08048424 in main ()
(gdb) x/1s 0x80c2894 //show data at this location
0x80c2894: "You Lose! Debuggering!...."
The string located at 0x80c2894 as you can see above is telling us that the program is probably about to end and after that instruction further down, one instruction before where we would have jumped if SF = 0, is JMP 0x080484f9. at that location is located:
80484f9: 8b 4d fc mov -0x4(%ebp),%ecx
80484fc: c9 leave
80484fd: 8d 61 fc lea -0x4(%ecx),%esp
8048500: c3 ret
8048501: 90 nop
8048502: 90 nop
As you can see on your own objdump too, the program is about to exit.
So lets go back to where the JNS instruction was and unset the SF flag so the jump gets executed.
SF is the 7th bit in the register so in order to cancel it we need to xor with 2^7 = 128
(gdb) set $eflags = $eflags ^ 128
(gdb) p $eflags
$4 = [ PF IF ]
Now the SF flag has been unset lets step into the next instruction:
(gdb) si
0x08048436 in main ()
We have successfully bypassed the ptrace() function and continued to execute the program.
Before we continue to execute set a breakpoint on the address: 0x08048495 - This is where the program will continue once you have pressed enter after entering your password.
(gdb) c
Continuing.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|| Welcome to an anti debug challenge !!!!! ||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Password : AAAAAAAA
Breakpoint 5, 0x08048495 in main ()
Now step to the instruction: 0x080484a3 using si...
80484a3: 38 c2 cmp %al,%dl
This is comparing %al and %dl the first 8 bits of the $eax and $edx registers. lets see what they are:
(gdb) p $al
$5 = 101
(gdb) p $dl
$6 = 65
101 in decimal is the value : e
65 in decimal is the value : A
did we not put AAAAAAAA as our password??? moving on...
They were not equal so the next instruction:
80484c1: 75 21 jne 80484e4 <_notng+0x4d>
Will take the jump to 0x080484e4 and this code looks like so:
80484e4: 83 ec 0c sub $0xc,%esp
80484e7: 68 8e 29 0c 08 push $0x80c298e
80484ec: e8 df 0d 00 00 call 80492d0 <_IO_puts>
80484f1: 83 c4 10 add $0x10,%esp
80484f4: b8 00 00 00 00 mov $0x0,%eax
80484f9: 8b 4d fc mov -0x4(%ebp),%ecx
80484fc: c9 leave
80484fd: 8d 61 fc lea -0x4(%ecx),%esp
As you might be able to gather from last time, this again is the exit routine and you see it calls _IO_puts before it exits with the argument from 0x080c298e... this will probably be the string "wrong password" or something:
(gdb) x/1s 0x080c298e
0x80c298e: "\nWrong password.\n"
Ahh there you go... so lets, before we continue, make sure the JNE instruction DOES NOT take the jump to the exit routine and continues exiting our code. we must change the Zero flag in order so it represents true.
The Zero Flag(ZF) is the 6th bit which in decimal is 2^6 = 64.
If any of you are experienced in reverse engineering, looking at the disassembled executable code, you may be able to instantly realize that the program is comparing %al with %dl and then checking if the Zero flag has been set, if it has carry on comparing. The program is comparing our password to something else? The real password?
80484a3: 38 c2 cmp %al,%dl
80484a5: 75 3d jne 80484e4 <_notng+0x4d>
80484a7: 8a 55 eb mov -0x15(%ebp),%dl
80484aa: 8b 45 f4 mov -0xc(%ebp),%eax
80484ad: 83 c0 05 add $0x5,%eax
80484b0: 8a 00 mov (%eax),%al
80484b2: 38 c2 cmp %al,%dl
80484b4: 75 2e jne 80484e4 <_notng+0x4d>
80484b6: 8a 55 ec mov -0x14(%ebp),%dl
80484b9: 8b 45 f4 mov -0xc(%ebp),%eax
80484bc: 40 inc %eax
80484bd: 8a 00 mov (%eax),%al
80484bf: 38 c2 cmp %al,%dl
80484c1: 75 21 jne 80484e4 <_notng+0x4d>
80484c3: 8a 55 ed mov -0x13(%ebp),%dl
80484c6: 8b 45 f4 mov -0xc(%ebp),%eax
80484c9: 83 c0 0a add $0xa,%eax
80484cc: 8a 00 mov (%eax),%al
80484ce: 38 c2 cmp %al,%dl
80484d0: 75 12 jne 80484e4 <_notng+0x4d>
80484d2: 83 ec 0c sub $0xc,%esp
80484d5: 68 7a 29 0c 08 push $0x80c297a
80484da: e8 f1 0d 00 00 call 80492d0 <_IO_puts> ; finally if we reached this far now print something ?
So lets step through the program now using
(gdb) si
and at each "cmp" instruction, note down the value of $al, then change the zero flag so we can progress to the next letter.
First set zero flag:
(gdb) si
0x080484a5 in main ()
(gdb) set $eflags = $eflags | 64
(gdb) p $eflags
$11 = [ CF AF ZF SF IF ]
(gdb) b * 0x080484b2
(gdb) c
Continuing.
Breakpoint 6, 0x080484b2 in main ()
(gdb) p $al
$12 = 97
_____________________________________________
0x080484a3 cmp %al,%dl ----> %al == 101 ="e"
0x080484b2 cmp %al,%dl ----> %al == 97 ="a"
______________________________________________
(gdb) si
0x080484b4 in main ()
(gdb) set $eflags = $eflags | 64
(gdb) b *0x080484bf
Breakpoint 7 at 0x80484bf
(gdb) c
Continuing.
Breakpoint 7, 0x080484bf in main ()
(gdb) p $al
$15 = 115
_____________________________________________
0x080484a3 cmp %al,%dl ----> %al == 101 ="e"
0x080484b2 cmp %al,%dl ----> %al == 97 ="a"
0x080484bf cmp %al,%dl ----> %al == 115 = "s"
_____________________________________________
----- can you tell what it might be yet.......continuing........
(gdb) b *0x080484ce
Breakpoint 8 at 0x80484ce
(gdb) si
0x080484c1 in main ()
(gdb) set $eflags = $eflags | 64
(gdb) c
Continuing.
Breakpoint 8, 0x080484ce in main ()
(gdb) p %al
A syntax error in expression, near `%al'.
(gdb) p $al
$16 = 121
_____________________________________________
0x080484a3 cmp %al,%dl ----> %al == 101 ="e"
0x080484b2 cmp %al,%dl ----> %al == 97 ="a"
0x080484bf cmp %al,%dl ----> %al == 115 = "s"
0x080484ce cmp %al,%dl ----> %al == 121 = "y"
_____________________________________________
(gdb) si
0x080484d0 in main ()
(gdb) set $eflags = $eflags | 64
So we have just stepped into the final JNE instruction, set the ZF bit in the $eflags register, and now if we continue, lets see what happens:
(gdb) c
Continuing.
Good password !!!
[Inferior 1 (process 4320) exited normally]
Oh, So we entered AAAAAAAA as the password... the password turned out to be "easy" but we win anyway!
root@fedvm /pentest/reverseEngineering # ./anti-Dbg.bin
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|| Welcome to an anti debug challenge !!!!! ||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Password : easy
Good password !!!
_________________________________________________________________________
Although the password was "easy", no pun intended, what has been shown is ptrace() is not enough alone for effective anti-Debugging techniques, and also password protections such as comparing each letter to the corresponding password letter, are also very poor and can easily be cracked.
I hope some of you learned something anyway, and there will be some more blog posts on reverse engineering and cracking soon, but not as simple as this :P
~m0x39
hmmm... Prerequisites:
* Linux OS
* gdb
* objdump
* x86 Assembly knoweledge
* Reverse Engineering basics
gdb and objdump should be installed on your Linux OS by standard, however if they are not you can install them from your favourite package manager.
Yes you will need perseverance if your a beginner to this because things can get tricky,
and basic knowledge of Assembly and reverse engineering binaries.
So lets get to it!
Firstly download the binary file from --> here <--
And lets begin some static analysis:
root@fedvm /pentest/reverseEngineering # file anti-Dbg.bin
anti-Dbg.bin: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.9, not stripped
So its an ELF 32-bit executable and its symbols have not been stripped which is always good for debugging.
lets run the file:
root@fedvm /pentest/reverseEngineering # ./anti-Dbg.bin
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|| Welcome to an anti debug challenge !!!!! ||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Password : password?
Wrong password.
So it gives us a password prompt but we have know way of possibly knowing what it could be. So lets get all static strings from the file, maybe it has been stored in a variable? If you run the command:
root@fedvm /pentest/reverseEngineering # cat anti-Dbg.bin | strings
You can see there is a lot of junk but among those strings you can find the text displayed at run time and password prompt with a simple '| grep "welcome" ' or ' | grep "password" '
However any other strings that look like they could be passwords are not. So next step...debugging the application to get the password.
root@fedvm /pentest/reverseEngineering # gdb -q anti-Dbg.bin
Reading symbols from /pentest/reverseEngineering/anti-Dbg.bin...(no debugging symbols found)...done.
(gdb) r
Starting program: /pentest/reverseEngineering/anti-Dbg.bin
You Lose! Debuggering!....
[Inferior 1 (process 3731) exited with code 01]
(gdb)
So the program has detected us debugging and doesn't even let us start to make any progress... unless we could stop the program at the beginning of execution? Before the anti-debugging has a chance to kick in? If its that type of AD technique... lets try it. Add a breakpoint to main.
(gdb) b *main
Breakpoint 1 at 0x80483f0
(gdb) r
Starting program: /pentest/reverseEngineering/anti-Dbg.bin
Breakpoint 1, 0x080483f0 in main ()
So we have added a breakpoint to main and it has now paused execution. (note. sometimes b *main wouldnt work because of symbols not being included during compilation or if the program utilizes an in-memory encryption-decryption algorithm, so the next step will explain how to set a breakpoint at the start of a program regardless of this issue).
Now we need analyze the x86 ASM code and step through the program avoiding the anti-debugging techniques. We do this using objdump.
root@fedvm /pentest/reverseEngineering # objdump -D anti-Dbg.bin > antiDebugObjDump
Now navigate inside this file to the line which says 080483f0 <main>:
(your address may be different to mine)
Here is the beginning of the program and the address is what you could use to also set the breakpoint on main if *main doesn't work...:
(gdb) b *0x080483f0
Now lets analyze the Assembly code whilst debugging the application, to bypass the anti-debugging techniques in place.
Firstly after the initial stack setup I see these instructions which look interesting:
8048401: c7 45 f4 88 28 0c 08 movl $0x80c2888,-0xc(%ebp)
So here a value located at -0xc(%ebp) is being loaded into the address 0x80c2888. I wonder what this is? Lets set a breakpoint here for later.
(gdb) b *0x08048401
Breakpoint 2 at 0x8048401
Next:
8048408: 6a 00 push $0x0
804840a: 6a 01 push $0x1
804840c: 6a 00 push $0x0
804840e: 6a 00 push $0x0
8048410: e8 5b 06 01 00 call 8058a70 <ptrace>
What we have here is arguments being pushed onto the stack for the function call ptrace at 0x08048410. If you already have C knowledge you may have seen this ptrace() function call before. You can use this function to check if any other processes attach to the current process which made the ptrace call. This is most likely how the ptrace is working.
lets continue:
(gdb) c
Continuing.
Breakpoint 3, 0x08048401 in main ()
(gdb) si
0x08048408 in main ()
//We are now at the instruction one after the the movl instruction which moved a value into 0x80c2888. Lets see what that value was:
(gdb) x/8s 0x80c2888
0x80c2888: "ksuiealohgy"
0x80c2894: "You Lose! Debuggering!...."
0x80c28af: ""
0x80c28b0: '+' <repeats 60 times>
0x80c28ed: ""
0x80c28ee: ""
0x80c28ef: ""
0x80c28f0: "|| Welcome to an anti debug challenge !!!!! ||"
So it saved the string "ksuiealohgy". hmmm lets ignore it for now but keep it in mind...
Also below we see other strings that we have encountered.
Before we go any further lets put a breakpoint on the next important instruction:
804841a: 79 1a jns 8048436 <main+0x46>
(gdb) b *0x0804841a
and continue using "c"...
(gdb) c
Continuing.
Breakpoint 4, 0x0804841a in main ()
We are now at the JNS instruction. This means Jump Short if Not zero and the value it is interested in is the SF (Sign flag) located in the FLAGS register. lets see what this value is:
(gdb) p $eflags
$1 = [ PF SF IF ]
It seems the SF flag is set so the jump will not be made so lets see what happens now when we continue:
804841c: 83 ec 0c sub $0xc,%esp
804841f: 68 94 28 0c 08 push $0x80c2894 ; what is this string being pushed onto the stack? it is what is going to be used as an argument in the next function puts().
8048424: e8 a7 0e 00 00 call 80492d0 <_IO_puts>
8048429: 83 c4 10 add $0x10,%esp
804842c: b8 01 00 00 00 mov $0x1,%eax
8048431: e9 c3 00 00 00 jmp 80484f9 <_notng+0x62>
8048436: 83 ec 0c sub $0xc,%esp
(gdb) si //step
0x0804841c in main ()
(gdb) si //step
0x0804841f in main ()
(gdb) si //step
0x08048424 in main ()
(gdb) x/1s 0x80c2894 //show data at this location
0x80c2894: "You Lose! Debuggering!...."
The string located at 0x80c2894 as you can see above is telling us that the program is probably about to end and after that instruction further down, one instruction before where we would have jumped if SF = 0, is JMP 0x080484f9. at that location is located:
80484f9: 8b 4d fc mov -0x4(%ebp),%ecx
80484fc: c9 leave
80484fd: 8d 61 fc lea -0x4(%ecx),%esp
8048500: c3 ret
8048501: 90 nop
8048502: 90 nop
As you can see on your own objdump too, the program is about to exit.
So lets go back to where the JNS instruction was and unset the SF flag so the jump gets executed.
SF is the 7th bit in the register so in order to cancel it we need to xor with 2^7 = 128
(gdb) set $eflags = $eflags ^ 128
(gdb) p $eflags
$4 = [ PF IF ]
Now the SF flag has been unset lets step into the next instruction:
(gdb) si
0x08048436 in main ()
We have successfully bypassed the ptrace() function and continued to execute the program.
Before we continue to execute set a breakpoint on the address: 0x08048495 - This is where the program will continue once you have pressed enter after entering your password.
(gdb) c
Continuing.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|| Welcome to an anti debug challenge !!!!! ||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Password : AAAAAAAA
Breakpoint 5, 0x08048495 in main ()
Now step to the instruction: 0x080484a3 using si...
80484a3: 38 c2 cmp %al,%dl
This is comparing %al and %dl the first 8 bits of the $eax and $edx registers. lets see what they are:
(gdb) p $al
$5 = 101
(gdb) p $dl
$6 = 65
101 in decimal is the value : e
65 in decimal is the value : A
did we not put AAAAAAAA as our password??? moving on...
They were not equal so the next instruction:
80484c1: 75 21 jne 80484e4 <_notng+0x4d>
Will take the jump to 0x080484e4 and this code looks like so:
80484e4: 83 ec 0c sub $0xc,%esp
80484e7: 68 8e 29 0c 08 push $0x80c298e
80484ec: e8 df 0d 00 00 call 80492d0 <_IO_puts>
80484f1: 83 c4 10 add $0x10,%esp
80484f4: b8 00 00 00 00 mov $0x0,%eax
80484f9: 8b 4d fc mov -0x4(%ebp),%ecx
80484fc: c9 leave
80484fd: 8d 61 fc lea -0x4(%ecx),%esp
As you might be able to gather from last time, this again is the exit routine and you see it calls _IO_puts before it exits with the argument from 0x080c298e... this will probably be the string "wrong password" or something:
(gdb) x/1s 0x080c298e
0x80c298e: "\nWrong password.\n"
Ahh there you go... so lets, before we continue, make sure the JNE instruction DOES NOT take the jump to the exit routine and continues exiting our code. we must change the Zero flag in order so it represents true.
The Zero Flag(ZF) is the 6th bit which in decimal is 2^6 = 64.
If any of you are experienced in reverse engineering, looking at the disassembled executable code, you may be able to instantly realize that the program is comparing %al with %dl and then checking if the Zero flag has been set, if it has carry on comparing. The program is comparing our password to something else? The real password?
80484a3: 38 c2 cmp %al,%dl
80484a5: 75 3d jne 80484e4 <_notng+0x4d>
80484a7: 8a 55 eb mov -0x15(%ebp),%dl
80484aa: 8b 45 f4 mov -0xc(%ebp),%eax
80484ad: 83 c0 05 add $0x5,%eax
80484b0: 8a 00 mov (%eax),%al
80484b2: 38 c2 cmp %al,%dl
80484b4: 75 2e jne 80484e4 <_notng+0x4d>
80484b6: 8a 55 ec mov -0x14(%ebp),%dl
80484b9: 8b 45 f4 mov -0xc(%ebp),%eax
80484bc: 40 inc %eax
80484bd: 8a 00 mov (%eax),%al
80484bf: 38 c2 cmp %al,%dl
80484c1: 75 21 jne 80484e4 <_notng+0x4d>
80484c3: 8a 55 ed mov -0x13(%ebp),%dl
80484c6: 8b 45 f4 mov -0xc(%ebp),%eax
80484c9: 83 c0 0a add $0xa,%eax
80484cc: 8a 00 mov (%eax),%al
80484ce: 38 c2 cmp %al,%dl
80484d0: 75 12 jne 80484e4 <_notng+0x4d>
80484d2: 83 ec 0c sub $0xc,%esp
80484d5: 68 7a 29 0c 08 push $0x80c297a
80484da: e8 f1 0d 00 00 call 80492d0 <_IO_puts> ; finally if we reached this far now print something ?
So lets step through the program now using
(gdb) si
and at each "cmp" instruction, note down the value of $al, then change the zero flag so we can progress to the next letter.
First set zero flag:
(gdb) si
0x080484a5 in main ()
(gdb) set $eflags = $eflags | 64
(gdb) p $eflags
$11 = [ CF AF ZF SF IF ]
(gdb) b * 0x080484b2
(gdb) c
Continuing.
Breakpoint 6, 0x080484b2 in main ()
(gdb) p $al
$12 = 97
_____________________________________________
0x080484a3 cmp %al,%dl ----> %al == 101 ="e"
0x080484b2 cmp %al,%dl ----> %al == 97 ="a"
______________________________________________
(gdb) si
0x080484b4 in main ()
(gdb) set $eflags = $eflags | 64
(gdb) b *0x080484bf
Breakpoint 7 at 0x80484bf
(gdb) c
Continuing.
Breakpoint 7, 0x080484bf in main ()
(gdb) p $al
$15 = 115
_____________________________________________
0x080484a3 cmp %al,%dl ----> %al == 101 ="e"
0x080484b2 cmp %al,%dl ----> %al == 97 ="a"
0x080484bf cmp %al,%dl ----> %al == 115 = "s"
_____________________________________________
----- can you tell what it might be yet.......continuing........
(gdb) b *0x080484ce
Breakpoint 8 at 0x80484ce
(gdb) si
0x080484c1 in main ()
(gdb) set $eflags = $eflags | 64
(gdb) c
Continuing.
Breakpoint 8, 0x080484ce in main ()
(gdb) p %al
A syntax error in expression, near `%al'.
(gdb) p $al
$16 = 121
_____________________________________________
0x080484a3 cmp %al,%dl ----> %al == 101 ="e"
0x080484b2 cmp %al,%dl ----> %al == 97 ="a"
0x080484bf cmp %al,%dl ----> %al == 115 = "s"
0x080484ce cmp %al,%dl ----> %al == 121 = "y"
_____________________________________________
(gdb) si
0x080484d0 in main ()
(gdb) set $eflags = $eflags | 64
So we have just stepped into the final JNE instruction, set the ZF bit in the $eflags register, and now if we continue, lets see what happens:
(gdb) c
Continuing.
Good password !!!
[Inferior 1 (process 4320) exited normally]
Oh, So we entered AAAAAAAA as the password... the password turned out to be "easy" but we win anyway!
root@fedvm /pentest/reverseEngineering # ./anti-Dbg.bin
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|| Welcome to an anti debug challenge !!!!! ||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Password : easy
Good password !!!
_________________________________________________________________________
Although the password was "easy", no pun intended, what has been shown is ptrace() is not enough alone for effective anti-Debugging techniques, and also password protections such as comparing each letter to the corresponding password letter, are also very poor and can easily be cracked.
I hope some of you learned something anyway, and there will be some more blog posts on reverse engineering and cracking soon, but not as simple as this :P
~m0x39
Monday 10 December 2012
Cracking 768bit RSA Encryption
0x00 Introduction
This post is going to be demonstrating a 768 bit RSA crack when all you have is the file you want to decrypt, and the public key. RSA isnt all that hard to crack given the correct circumstances, however this wont be the case all the time so you may be in need of a lot of processing power.
A brief info on RSA encryption and public/private keys... in public-key cryptography the keys are signed with a key algorithm and in this case it is RSA which is an asymmetric algorthim and this uses integer factorization as the basis of the cryptographic method, as you will find out later.
0x01 RSA public/private key generation
In RSA, the private key is generated (d,p,q), the public key is generated (e,n):
We have a file which has been encrypted and all we have is the public key below which is available to anyone. We can however, deduce the private key from the public key, if the circumstances are correct.
0x03 Math-o-crypto practical
We have our public and file that we want to decrypt...
First step is to extract public key modulus and public key exponent (n, e):
root@vm:~/Desktop/RSAcrack/# pkcs1-conv publickey.pem | xxd
0000000: 2831 303a 7075 626c 6963 2d6b 6579 2839 (10:public-key(9
0000010: 3a72 7361 2d70 6b63 7331 2831 3a6e 3733 :rsa-pkcs1(1:n73
0000020: 3a00 c2cb b24f dbf9 23b6 1268 e3f1 1a38 :....O..#..h...8
0000030: 96de 4574 b3ba 5873 0cbd 6529 3886 4e22 ..Et..Xs..e)8.N"
0000040: 23ee eb70 4a17 cfd0 8d16 b468 91a6 1474 #..pJ......h...t
0000050: 7599 39c6 e49a afe7 f259 5548 c74c 1d7f u.9......YUH.L..
0000060: b8d2 4cd1 5cb2 3b4c d0a3 2928 313a 6533 ..L.\.;L..)(1:e3
0000070: 3a01 0001 2929 29 :...)))
(I like to use pkcs1-conv from the nettle-bin package to do this step though it can be done with other methods)
From this information n can be obtained from bytes 0x21 - 0x69
I know this because after the header with "(1:n73", after the final character 0x3a, begins the modulus, it ends before the signature 0000060: ... 29 28 31 3a 65 33 3a ...
n = 0xc2cbb24fdbf923b61268e3f11a3896de4574b3ba58730cbd652938864e2223ee eb704a17cfd08d16b46891a61474759939c6e49aafe7f2595548c74c1d7fb8d24cd1 5cb23b4cd0a3
e = 0x010001 (from bytes 0x71-0x73)
These now need to be turned into integers so load up python or whatever you want:
root@vm:~/Desktop/RSAcrack/# python
>>> int("0xc2cbb24fdbf923b61268e3f11a3896de4574b3ba58730cbd652938864e2223ee eb704a17cfd08d16b46891a61474759939c6e49aafe7f2595548c74c1d7fb8d24cd1 5cb23b4cd0a3", 16)
This post is going to be demonstrating a 768 bit RSA crack when all you have is the file you want to decrypt, and the public key. RSA isnt all that hard to crack given the correct circumstances, however this wont be the case all the time so you may be in need of a lot of processing power.
A brief info on RSA encryption and public/private keys... in public-key cryptography the keys are signed with a key algorithm and in this case it is RSA which is an asymmetric algorthim and this uses integer factorization as the basis of the cryptographic method, as you will find out later.
0x01 RSA public/private key generation
In RSA, the private key is generated (d,p,q), the public key is generated (e,n):
- p = randomly chosen prime
- q = randomly chosen prime
- n = modulus for public and private keys(n=pq)
- f(n)=(p-1)(q-1) :: f(n) counts the number of positive integers less than or equal to n that are relatively prime to n
- e = exponent (chosen as 1 < e < f(n) && greatest common divisor of (e, f(n)) = 1... so e and f(n) are coprime) this is the public key exponent
- d = e^-1(mod f(n)) or (de) = 1 mod f(n) --- this is the private key exponent
We have a file which has been encrypted and all we have is the public key below which is available to anyone. We can however, deduce the private key from the public key, if the circumstances are correct.
0x03 Math-o-crypto practical
root@vm:~/Desktop/RSAcrack/#
cat publickey.pem
-----BEGIN PUBLIC KEY----- MGQwDQYJKoZIhvcNAQEBBQADUwAwUAJJAMLLsk/b+SO2Emjj8Ro4lt5FdLO6WHMM vWUpOIZOIiPu63BKF8/QjRa0aJGmFHR1mTnG5Jqv5/JZVUjHTB1/uNJM0VyyO0zQ owIDAQAB
-----END PUBLIC KEY-----
root@vm:~/Desktop/RSAcrack/# cat file2crack.bin
0000000: 7bca 100e 286c 9a4b e34f 7b19 7be1 04f2 {...(l.K.O{.{...
0000010: 5c0d bc11 2c15 e818 17af 8e38 53a2 47a8 \...,......8S.G.
0000020: 0cb4 c671 c5b6 bf6c 880b 503f 2957 7c84 ...q...l..P?)W|.
0000030: 7f48 0e39 f1ee 0796 c2de f426 a3b6 c4e0 .H.9.......&....
0000040: f708 29fa 4519 9040 ..).E..@
-----BEGIN PUBLIC KEY----- MGQwDQYJKoZIhvcNAQEBBQADUwAwUAJJAMLLsk/b+SO2Emjj8Ro4lt5FdLO6WHMM vWUpOIZOIiPu63BKF8/QjRa0aJGmFHR1mTnG5Jqv5/JZVUjHTB1/uNJM0VyyO0zQ owIDAQAB
-----END PUBLIC KEY-----
root@vm:~/Desktop/RSAcrack/# cat file2crack.bin
0000000: 7bca 100e 286c 9a4b e34f 7b19 7be1 04f2 {...(l.K.O{.{...
0000010: 5c0d bc11 2c15 e818 17af 8e38 53a2 47a8 \...,......8S.G.
0000020: 0cb4 c671 c5b6 bf6c 880b 503f 2957 7c84 ...q...l..P?)W|.
0000030: 7f48 0e39 f1ee 0796 c2de f426 a3b6 c4e0 .H.9.......&....
0000040: f708 29fa 4519 9040 ..).E..@
We have our public and file that we want to decrypt...
First step is to extract public key modulus and public key exponent (n, e):
root@vm:~/Desktop/RSAcrack/# pkcs1-conv publickey.pem | xxd
0000000: 2831 303a 7075 626c 6963 2d6b 6579 2839 (10:public-key(9
0000010: 3a72 7361 2d70 6b63 7331 2831 3a6e 3733 :rsa-pkcs1(1:n73
0000020: 3a00 c2cb b24f dbf9 23b6 1268 e3f1 1a38 :....O..#..h...8
0000030: 96de 4574 b3ba 5873 0cbd 6529 3886 4e22 ..Et..Xs..e)8.N"
0000040: 23ee eb70 4a17 cfd0 8d16 b468 91a6 1474 #..pJ......h...t
0000050: 7599 39c6 e49a afe7 f259 5548 c74c 1d7f u.9......YUH.L..
0000060: b8d2 4cd1 5cb2 3b4c d0a3 2928 313a 6533 ..L.\.;L..)(1:e3
0000070: 3a01 0001 2929 29 :...)))
(I like to use pkcs1-conv from the nettle-bin package to do this step though it can be done with other methods)
From this information n can be obtained from bytes 0x21 - 0x69
I know this because after the header with "(1:n73", after the final character 0x3a, begins the modulus, it ends before the signature 0000060: ... 29 28 31 3a 65 33 3a ...
n = 0xc2cbb24fdbf923b61268e3f11a3896de4574b3ba58730cbd652938864e2223ee eb704a17cfd08d16b46891a61474759939c6e49aafe7f2595548c74c1d7fb8d24cd1 5cb23b4cd0a3
e = 0x010001 (from bytes 0x71-0x73)
These now need to be turned into integers so load up python or whatever you want:
root@vm:~/Desktop/RSAcrack/# python
>>> int("0xc2cbb24fdbf923b61268e3f11a3896de4574b3ba58730cbd652938864e2223ee eb704a17cfd08d16b46891a61474759939c6e49aafe7f2595548c74c1d7fb8d24cd1 5cb23b4cd0a3", 16)
188198812920607963838697239461650439807163563379417382700763356422988859715234665485319060606504743045317388011303396716199692321205734031879550656996221305168759307650257059L
>>> int("0x10001", 16)
65537
n = 188198812920607963838697239461650439807163563379417382700763356422988859715234665485319060606504743045317388011303396716199692321205734031879550656996221305168759307650257059L
e = 65537
Now this is where the luck or processing power will come in... we need to find the factors (p,q) from the modulus (n) integer. The first place to look is a factor database which have already been generated so go to factordb.com and enter your modulus:
http://www.factordb.com/
I happen to have two factors returned so save these and now these are your p and q parameters, if you dont happen to find factors already on the web you will have to try and generate them yourselves, and this is what makes RSA harder to crack as more bits are used in generation
so now:
p = 398075086424064937397125500550386491199064362342526708406385189575946388957261768583317
q = 472772146107435302536223071973048224632914695302097116459852171130520711256363590397527
Everything we need apart from the private key exponent (d) which we can hopefully deduce from the information currently owned(p, q, n, e).
There is a python script which can generate RSA algorithms given the correct parameters, so run this through rsatool.py -p -q -n -e
(https://raw.github.com/ius/rsatool/master/rsatool.py)
root@vm:~/Desktop/RSAcrack/# python rsatool.py -p 398075086424064937397125500550386491199064362342526708406385189575946388957261768583317 -q 472772146107435302536223071973048224632914695302097116459852171130520711256363590397527 -n 188198812920607963838697239461650439807163563379417382700763356422988859715234665485319060606504743045317388011303396716199692321205734031879550656996221305168759307650257059 -e 65537
Using (p, q) to initialise RSA instance
n =
c2cbb24fdbf923b61268e3f11a3896de4574b3ba58730cbd652938864e2223eeeb704a17cfd08d16
b46891a61474759939c6e49aafe7f2595548c74c1d7fb8d24cd15cb23b4cd0a3
e = 65537 (0x10001)
d =
32030e42c69d4e77de7e2397b13dba2e52f2c57a205f5973fed6f87632f53cf8886609ff63fa114e
2b5df1db6249f8eaf0bf5fa26ad5b8e48b7fab050d32fc574b446e22d08ba7b1
p =
cce95457f127c49546e57841029ac6af70604c64e8281018acbb538233bb57f37a6e6895
q =
f35cb825f003396f11f149a59a0fe73db43162cb305b8ebfeda5ca840be24c536b6aae57
We now have been given d which is the private key exponent which has been generated via: d = e^-1(mod f(n))
All you need now is a short python script which I found on the net which uses all the paramaters you have found to decrypt the original file and you have cracked 768 bit RSA
RSAcrack.py:
#!/usr/bin/python
from sys import*;from string import*;a=argv;[s,p,q]=filter(lambda x:x[:1]!=
'-',a);d='-d'in a;e,n=atol(p,16),atol(q,16);l=(len(q)+1)/2;o,inb=l-d,l-1+d
while s:s=stdin.read(inb);s and map(stdout.write,map(lambda i,b=pow(reduce(
lambda x,y:(x<<8L)+y,map(ord,s)),e,n):chr(b>>8*i&255),range(o-1,-1,-1)))
Usage : cat file | python rsacrack.py -d [private key exponent] [public key modulus]
Ill run this command and pipe it to Strings as it is strings Im after:
root@vm:~/Desktop/RSAcrack/# cat file2crack.bin | python RSAimplement.py -d 32030e42c69d4e77de7e2397b13dba2e52f2c57a205f5973fed6f87632f53cf8886609ff63fa114e2b5df1db6249f8eaf0bf5fa26ad5b8e48b7fab050d32fc574b446e22d08ba7b1 C2CBB24FDBF923B61268E3F11A3896DE4574B3BA58730CBD652938864E2223EEEB704A17CFD08D16B46891A61474759939C6E49AAFE7F2595548C74C1D7FB8D24CD15CB23B4CD0A3 | strings
Ae"h
up2l6DnaIhZgxA
And there you have it, the decrypted message was:
Ae"h
up2l6DnaIhZgxA
----------------------------------------------------------------
Any questions feel free to comment below!
Hope this was of help to some of you who dont already know it!
~m0x39
65537
n = 188198812920607963838697239461650439807163563379417382700763356422988859715234665485319060606504743045317388011303396716199692321205734031879550656996221305168759307650257059L
e = 65537
Now this is where the luck or processing power will come in... we need to find the factors (p,q) from the modulus (n) integer. The first place to look is a factor database which have already been generated so go to factordb.com and enter your modulus:
http://www.factordb.com/
I happen to have two factors returned so save these and now these are your p and q parameters, if you dont happen to find factors already on the web you will have to try and generate them yourselves, and this is what makes RSA harder to crack as more bits are used in generation
so now:
p = 398075086424064937397125500550386491199064362342526708406385189575946388957261768583317
q = 472772146107435302536223071973048224632914695302097116459852171130520711256363590397527
Everything we need apart from the private key exponent (d) which we can hopefully deduce from the information currently owned(p, q, n, e).
There is a python script which can generate RSA algorithms given the correct parameters, so run this through rsatool.py -p -q -n -e
(https://raw.github.com/ius/rsatool/master/rsatool.py)
root@vm:~/Desktop/RSAcrack/# python rsatool.py -p 398075086424064937397125500550386491199064362342526708406385189575946388957261768583317 -q 472772146107435302536223071973048224632914695302097116459852171130520711256363590397527 -n 188198812920607963838697239461650439807163563379417382700763356422988859715234665485319060606504743045317388011303396716199692321205734031879550656996221305168759307650257059 -e 65537
Using (p, q) to initialise RSA instance
n =
c2cbb24fdbf923b61268e3f11a3896de4574b3ba58730cbd652938864e2223eeeb704a17cfd08d16
b46891a61474759939c6e49aafe7f2595548c74c1d7fb8d24cd15cb23b4cd0a3
e = 65537 (0x10001)
d =
32030e42c69d4e77de7e2397b13dba2e52f2c57a205f5973fed6f87632f53cf8886609ff63fa114e
2b5df1db6249f8eaf0bf5fa26ad5b8e48b7fab050d32fc574b446e22d08ba7b1
p =
cce95457f127c49546e57841029ac6af70604c64e8281018acbb538233bb57f37a6e6895
q =
f35cb825f003396f11f149a59a0fe73db43162cb305b8ebfeda5ca840be24c536b6aae57
We now have been given d which is the private key exponent which has been generated via: d = e^-1(mod f(n))
All you need now is a short python script which I found on the net which uses all the paramaters you have found to decrypt the original file and you have cracked 768 bit RSA
RSAcrack.py:
#!/usr/bin/python
from sys import*;from string import*;a=argv;[s,p,q]=filter(lambda x:x[:1]!=
'-',a);d='-d'in a;e,n=atol(p,16),atol(q,16);l=(len(q)+1)/2;o,inb=l-d,l-1+d
while s:s=stdin.read(inb);s and map(stdout.write,map(lambda i,b=pow(reduce(
lambda x,y:(x<<8L)+y,map(ord,s)),e,n):chr(b>>8*i&255),range(o-1,-1,-1)))
Usage : cat file | python rsacrack.py -d [private key exponent] [public key modulus]
Ill run this command and pipe it to Strings as it is strings Im after:
root@vm:~/Desktop/RSAcrack/# cat file2crack.bin | python RSAimplement.py -d 32030e42c69d4e77de7e2397b13dba2e52f2c57a205f5973fed6f87632f53cf8886609ff63fa114e2b5df1db6249f8eaf0bf5fa26ad5b8e48b7fab050d32fc574b446e22d08ba7b1 C2CBB24FDBF923B61268E3F11A3896DE4574B3BA58730CBD652938864E2223EEEB704A17CFD08D16B46891A61474759939C6E49AAFE7F2595548C74C1D7FB8D24CD15CB23B4CD0A3 | strings
Ae"h
up2l6DnaIhZgxA
And there you have it, the decrypted message was:
Ae"h
up2l6DnaIhZgxA
----------------------------------------------------------------
Any questions feel free to comment below!
Hope this was of help to some of you who dont already know it!
~m0x39
Wednesday 21 November 2012
Adding new resolution to monitor/laptop/dual-mon
So today I set up this blog because I have been programming in several languages and been highly enthusiastic about computer security for 10 years now and I thought... Now blog time must commence! So here is my first post...
Just a little python script I wrote to add a custom resolution and apply it to a screen of your choice, seeing as today I set up a dual monitor and my drivers didn’t pick up a res > 1024x768... and it ended up being a few commands to get it all sorted ... so here it is... enjoy!
newRes.py
Just a little python script I wrote to add a custom resolution and apply it to a screen of your choice, seeing as today I set up a dual monitor and my drivers didn’t pick up a res > 1024x768... and it ended up being a few commands to get it all sorted ... so here it is... enjoy!
newRes.py
Subscribe to:
Posts (Atom)