Thursday, May 27, 2021

Montevideo

 Break Main

Continue to Main,

Step into login


Looks like we have some new functions, getsn function looks similar to the past, however strcpy and then memset follows getsn, and before conditional_unlock_door.


Break at each, continue and input test password.


Password stored at 0x2400



Continue to strcpy, and step through.

strcpy is grabbing the first byte at 2400 (my password), putting it into r12, and then putting r12 into the 0x0 byte of r13 (currently pointed at 43ee). It then tst to see if r12 is 00, if not, it loops back up and repeats. So its moving my entire password. Then it just hit me, they probably are not writing these programs in assembly, and likely C, and so this probably matches strcpy(). Wow, I feel silly for going through the previous functions soooo manually.... 

ANYWAYS, continue through the rest of strcpy, to the breakpoint at memset. Confirmed my password has been copied to 0x43ee.

Step into memset, and this time I pre-read memset() to get an idea of what I should be seeing. and sure enough, 2 bytes at a time, my password at 0x2400 is being set to \x0000

Continue through until conditional_unlock_door function. Which looks the same as the previous, so this hasnt changed since the previous challenges. Which means no matter what I do, that r15 register will be \x0000 and the tst r15 instruction will always fail.



So, the last two challenges were overflows, lets try that again.


RESET

New pass



Unbreak strcpy and memset and conditional_unlock_door, and continue right through to the end.


Sure enough, same crash, same incorrect buffer size, just the added set of the strcpy and memset.

So first thought is to reset the unlock door function in my filler just like the last challenge.

For reference, the unlock door function from Cusco looks like:

3012 7f00    push   #0x7f
b012 4245   call     #0x4542
2153            incd    sp
3041            ret

 So 26 char buffer, and Ill want to land the memory location to execute right on the 17 char. Looking at memory at the time of crash, it looks like my pass is only located at 43ee

So my new pass will look like: 30127f00b01242452153304190909090ee43

RESET


Continue through to the end for it to execute my shellcode.

Aaaaand it just cleanly exits. Looking at memory, it looks like i have a problem, not all of my 'password' copied to 43fe. it stops after 7f00.


Looks like there are some bad chars, so, Ill run through all hex into the password, and try to identify bad characters.

RESET 

New pass: (All chars)

Continue through until end. Look at memory.


Looks like nothing got copied over, or maybe just \x00? First Char in my password is \x00, which is very very commonly a bad char, so I remove 00 from the beginning of my pass, and try again.

RESET

New Pass: (All chars, starting at 01)


Continue through to the end, and inspect memory for bad chars.


Looks good, however the input is truncated at 32 chars, so I trim the first 32 chars off the front of my password, and repeat multiple times until I get through all Chars.

Ill spare you the screenshots of every attempt, and tell you the results. No bad Chars, so it looks like \x00 is my only bad char to worry about.

So I need to ensure my password doesnt contain \x00. Which introduces a new challenge, as the unlock code is \x7f00, which contains a bad char. 

My first instinct is to look for any existing instructions in the disassembly view that would contain the unlock code.


Notta, I have to send it myself, but I cannot. So my next thought here is to look at how I can send something else, and then modify it later. I sent 4x nops in my password, that means I have that much space to modify my string, my first instruction is push \x7f00, so Ill change that to push \x7f01, and run through until crash. Then Ill inspect memory state at that time, and see what the assembly looks like, and see if I can identify anything that will change \x7f01 to \x7f00.

RESET

New Pass: 30127f01b01242452153304190909090ee43

Continue through to end. Excellent, it jumps to 43ee, with the instruction push #0x17f


Step once so \x7f01 is pushed onto the stack, then pause and take a look around.


sp is pointed at \x7f01, r12 and r5 are pointed to the middle of nowhere, and everything else is \x0000

Here I spent a good 15-20m looking at instructions. Initially I wanted something like mov.b #0x00 0x1(sp), which of course didnt exist, that would be too easy I guess?

I would write it myself, if I knew how, but I have only every used msf to generate hex representation of x86 assembly, and it doesnt look like msf does RISC. I could try the x86 instructions, but I chose not to go that direction. Ideally I would have an instruction sheet, or maybe even a program that I can put in mov.b #0x00 0x1(sp) and have it spit out its proper hex values.

So eventually I see this little section of instructions here. 



When Looking at this, since sp is currently pointed to \x7f01, I'm thinking I would push sp into r4, then move a byte that is currently \x00 into r4 to overwrite \x01 with \x00.

Soooo endianness will be tricky, but I THINK I can do something like this:


3012 7f01 push #0x7f01
0441 mov sp,r4
2453 incd r4
c443 fcff mov.b #0x0, -0x4(r4)
b0124c45 call #x4c45 <INT>

 I know this wont work, I'm going to mangle the wrong byte, but for my sanity, I'll chuck this in, observe how close I get, and then attempt to modify from there.

RESET

New Pass: 30127f0104412453c443fcffb0124c45ee43

Overflow to password location, execute push, mov, and incd r4 all work correctly.




Then I take a close look at memory while I step trough the mov.b instruction to see how far off I am.


Looks like 3 bytes too early, so I have to modify the c443 fcff instruction to try and get it to be -0x1(r4) instead. Once again, Im not sure of this, so I start looking at all of the instructions with mov.b, r4, 0x0 in them, to try and identify what is what. looks like the mov instructions are 4e/4b/44/etc. So Im guessing here 43 is the mov.b instruction. I see multiple mov.b commands that are mov 0x0 and they all look to have a similar format of c# before 4e, so Im guessing c4 here is the 0x0, which means fcff is the -4r4 instruction? So I look around for other instances of r4, and -0x, and I believe the fc part is the offset (-4) and the ff is r4, so giving it a test Ill change fc to ff, which is 3 bytes higher, and that should equal -0x1(r4)?? Worth a shot.

RESET

New Pass: 30127f0104412453c443ffffb0124c45ee43

I was right!


Step through the instruction:


And if you look at 0x43fe, its now \x7f00, and sp is still pointed to the start of it. My next instruction is call 0x454c





Cool, got my endianness correct.

Hit f to continue through to the end of the function




Notes:

Another fun one. I did far less detail on the mulling around ideas aspec. I had though of, and tried a couple others, like for example: I found 0312 push #0x0 instruction, so I tried incd sp and pushing \x00 onto the stack, then moving sp back, but was unable to get it to work. So I went back to skimming, tried something else, back to skimming. The solution of moving sp into r4 and mov.b -0x4(r4) came on the 4th attempt. 

I kept forgetting to remove or add nops into the buffer, so many times I would put something in, then execution would jump to random locations because I was 1 byte off. Overall, got it in a couple hours, so I thought that was decent for how green I am.

Fun Fun Fun.



Share:

0 comments:

Post a Comment