Saturday, May 29, 2021

Santa Cruz

 Break Main

Continue into Main

Sets sp and then calls login.



step into login

First half of login:


Looking at the strings, looks like there will be a username now. 

Looks like it prompts for username at 0x458a, and then for password at 0x45b4. Ill break just after both. continue through and input test credentials.


Looks like my input is being placed at 0x2404 and then copied to 0x43a2 (username) and 0x43b5 (password)






Remainder of login function:


Looks like next immediate steps are moving some registers around, and then at 0x45da there is a tst.b call. break at that, and take a look at what's being tested.

Looks like it is confirming that r14 is \x00, r14 is pointed at 0x43b5 (Start of our password), and looking at memory, it is not \x00 and so the jnz will execute back up to 0x45d8, inc r14 retest and loop. this appears to be determining how long our password is. Break just after loop, continue through. 

Next it moves r14 into r11, substracts r15 from r11, then moves the byte at 43b4 into r5, compares r15 to r11, and then jumps, Ill break at the cmp and look at register state at that time.

Looks like this compare will fail, and so we jump.





move byte at 0x43b3 into r15, and another cmp. This time, the registers match, and so the jc will execute.


Next up, there is a lot of moving of registers, lots of pushes, mov, and add. Of note though, is the push of 0x7d right before the call to INT function.





Im going to break at the tst.b just after the INT call, and continue through everything. After INT completes, it tests 0x43A0 which is \x00 currently, so the jz right after will execute. This puts password not correct to screen, and ultimately exit out of program cleanly.

So, nothing much there, nothing that I can look at to see the password compare to and no password in memory. So, blow up inputs with As and see if it is vulnerable to overflows.

RESET
New Username: (1000 As)
New Password:  (1000 Bs)

After I input my username, inspecting memory, it does appear to accept >16 chars, but is eventually truncated.


After Password input, and strcpy, it does appear that password accepts > 16 chars too, and is also truncated.


Continue through and I get password length too long error and it cleanly exits.
My first thought, is that I do not get username too long, and since my password was shoved right on top of my username, maybe I can overflow username, input correct length password, and maybe the username will still crash out the app?

RESET

Username: 1000x As
Password:  16x Bs

Memory directly after password's strcpy

As I continue through the rest of the execution, I now get password length too short?
Reset
Same inputs, step through execution manually, and observe closer.

The first cmp passes, which it should. (If it doesnt pass, it doesnt jump, and carrys on downwards to the br right below.) So all good so far I believe.



However this time, the second cmp does not match, so this will fail, it will not jump, and exit out at the br just below.  Found my issue?


It looks like r15 is set 2 instructions higher, via the mov.b instruction. -0x19r4 is currently located at 43B3 and is indeed 41

It is comparing it against \x10. So I count of that bytes location, looks like its the 18th bit, so can I just change the 18th char to \x10 and pass this jump?

RESET 
New username:  4141414141414141414141414141414141104141414141414141414141414141414141414141414141414141414141414141414141414141414141414141

Password: 16x Bs

Continue through to those cmps again. 
First cmp still fails, as it should.


Second cmp looks better now!

Looks like I got past the length checks, even with an overflowed username!

Ill step through the rest of the execution to see if I get a crash. But I do not. It cleanly exits. There are a few more jmps and tsts in the remaining execution, so Ill look at those closer.

RESET

Same username and pass.

Continue through to the first new tst.b / jz instruction.

Here we are testing the byte at 0x43A0 and if \x00, jumping. That byte is indeed \x00, so we jump to 0x4644. Unfortunately that Byte is before the location of our username and password, it doesnt appear that I can affect this byte as of this point in program execution.

Step through to the next tst.b / jz instruction.




Here we are testing the byte at 0x43C6, if \x00 we jump to 0x465e which is just after the br instruction. If it is not \x00 we do not jump, and exit the program. Currently the byte at 0x43C6 is \x41 so this will not jump. But the byte just before is \x00, and I did not add any null bytes to my input, and this null byte is just after my password. So it looks like it is inserting a null byte after my password on its own.
Can I just make the password 1 char longer and push that \x00 into the right location to jump? 


Reset
Same Username
New pass: 17x B's


Continue through to that tst.b instruction and it looks like 0x43C6 is now \x00. So I should jump to below the br. 




And I do!

And when I step through the remainder of the program, I crash it out with PC pointed at 4141!

So now I got to find which pair of \x41 it is pointed to at time of crash, and I control pc. Looking at the sp at the time of crash, it is pointed to 0x43ce, which is in my over flowed As.




And is 45 bytes after the start of my username. Lets put \x4343 there and see if I got pc correct. 
RESET
New username: 
414141414141414141414141414141414110414141414141414141414141414141414141414141414141414143434444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444

Pass: 17x Bs


NOPE! I was wrong. But it looks like It is in my As, and not my Cs or Ds. So Ill swap the As out just after the pass to Es and identify if pc is pointed to the As before the password, or after.

RESET
New Username: 
414141414141414141414141414141414110454545454545454545454545454545454545454545454545454543434444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444

Pass: 17x Bs

And it looks like it is pointed to 0x4545, so I have narrowed down PC a little more.

Next, Ill change everything to As, except for the section of PC, which Ill increment. However my password overwrites 17x bytes, starting  1x byte after \x10, and then the null byte. So I can likely also ignore that part too, and increment only this section here...




RESET
New Username:
4141414141414141414141414141414141104545454545454545454545454545454545454545454646474748414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141

Pass: 17x Bs

Continue through to the end, and step once out of login, and pc is pointed to 0x4847

Cool, I have identified pc location and now control it. So in my username, I can replace the occurrence of \x4748 with anything I want.

Lets go find something to put there.


It looks like this revision contains the unlock door function, so my first thought is to just put in 0x444a at pc, and see if that works.

RESET
New Username:
4141414141414141414141414141414141104545454545454545454545454545454545454545454646474a44414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141

Pass: 17x Bs

Continue through until we ret out of login, and step once. pc is pointed at 444a as we wanted, and it looks correct!


Hit continue and see if we unlock.




Unlocked! All is right with the world...

Notes:
I thought this was a good challenge as well. Adding the Username field was a nice touch, it added a little complexity, but nothing that I wasn't able to overcome. Nothing through me for tooooo much of a loop, and the realization that I dont have to step through things like puts, strcpy, memset, int, and stuff like that has REALLY sped up RE time. Overall this was fun. 


Share:

Friday, May 28, 2021

Johannesburg

Break main

Continue into main

Only 1 function, login

Step into login


Move sp to 43ec and then shove \x7e into it.

Looks like it puts strings to screen, gets input, then calls strcpy, then checks password. Will break at test password valid function, continue through until break point, input test password, and note memory location of password just prior to test.



Test password is located at 0x43ec AND 2400. No memset called after strcpy this time...

Set breakpoint right after this call at tst r15, and step into function. 


While slightly different, it appears that this does the same nonsense as the other check password functions from previous challenges (push \x00 into -0x4r4, then mov.b -0x4r4 into r15 right before return)

Step through and observe activity, just in case I'm wrong. Looks like its the same. r15 set to 0 on exit of test, doesnt appear to be any password comparing at all?

Back in login function, looks like tst will rail and we will jump. I set many breakpoints at all the jmps, calls, returns.



Stepping through the rest of the login function, we fail the tst and jump down to 0x3f40 and put "this password is incorrect"

Then it checks to see if \x7e is 17 bytes after sp. Sp is currently pointed at the start of my password. 





It looks like 7e is there, from the instruction at 0xf140. 

this cmb.p will pass, and to we will jump to 0x3150, move sp 18 bytes, ret our of login into stop_progExec.

RESET

Fill with As



Continue through, fail the tst, and step through the remainder of login. This time however, I fail the cmp.b, so I do not jump, and I continue down to mov / put "Invalid Password Length: password too long" and then break program execution.




So no matter what I do, I need the 17th byte to be \x7e, so reset, fill with \x7e.


Continue though to 0xf190 where the cmp.b \x7e is, step through and jump down to the add instruction.



After the cmp and jeq, is successful, we can see that there are indeed more bytes than 16, and if we step through the remainder of the program, we can see that it does indeed try to execute 0x7e7e  before it finished executing, and then crashes.


RESET

Continue through until password prompt

Lets try and control pc, 

I know the 17th byte needs to be 7e, so I need to identify where in the buffer it is trying to execute. My first instinct is that I will need to pass it a memory location that either starts with or ends with 7e. So Ill fill first 16x bytes with A and then 7e, and the last 16 bytes with B.


Except it cleanly exits.



I'm thinking endianness is off, and even though I input 7e as the 17th byte, its taking the input of 7e42, and little endianing (<--- is endianing a word?) them in memory to be 427e. I check memory, and it looks like I just miss counted.....

Reset, try again.

This time, 7e is in the 17th byte location, however it still cleanly exits.


Ill add another 7e so the 17th an 18th byte are both 7e, incase its inverting my bytes.

Success!

so it looks like its attempting to execute 4242 upon crash.




Ill change up the second half of my password string, with all hex options (but not \x00) and see exactly which chars I need to change up.



Continue through until crash.


Looking at pc at time of crash, it appears to be executing 0201, so its the first two bytes after 7e that I need to put my memory location into. 

Looking through the disassembly, it looks like the unlock door function is in this program.



login function calls 0x4446 <unlock_door>, so I scroll to 4446, and it is indeed there.


It is indeed there, and it looks the same as the previous unlock door functions. So Ill put in that memory location.

RESET

New Pass: 414141414141414141414141414141417e7e4644

Continue through until end and BOOM


Door unlocked.


Notes:

I'm a little confused on MC's challenge order. This one was SIGNIFICANTLY easier than the previous challenge, which I had to complete in order to unlock this challenge. I think I must have missed something in the previous challenge, and I made it harder than it needs to be? Anyways, this was a fun little one.


Share: