Per usual, run through the program as normal.
Break Main, only 1 function, login.
C to continue, input password, note down password location in memory.
Password is stored at 0x3630
Step through after password, return back to login.
So as we come out of "conditional_unlock_door" function, r15 needs to be set.
I'll break at this function for future, and step in.
As I stepped through this, this conditional unlock door was VERY similar to Cusco. It sets -0x4(f4) to null, and then at the end moves that into r15. Another very similar "not comparing the password, and will always exit function with r15 0000" function.
So naturally, these developers messed up the previous code base and allowed a BO, so lets try that again. BUT FIRST, I'll step through as normal, and look for instructions being executed close to the passwords memory space. (That's what I learned from Cusco! Observe to the bitter end.)
My password is located at 3630 and so I'm keeping an eye on PC for anything close to that. Most of the execution is in the 4xxx space.
When I step through execution, nothing seems to execute close to that address space.
Previously they truncated their input at 48 chars, maybe that has been removed in this revision and I can overflow all the way up into the 4xxx memory space? I'm going to overwrite something important....
RESET
New password (2000 As)
So I can overflow a little. It is certainly not confined to 16 chars. Looks like that truncation is still there.
So I'll step through this again. See if my As are referenced anywhere.
My first step through "conditional_unlock_door" is the same. It doesn't even reference the password, and sets r15 \x0000 right before exit.
Back in the login function, I expect the same tst to fail, jump down to 4522, put the string to screen, and then close out program.
I was correct, right up to the close out program. It looks like somewhere in the puts statement my As are referenced? I got a big ol' crash when it tried to RET out of the login function. I just love watching things try to execute 4141!
So we DO have a buffer overflow here. I'll throw in my all hex chars and see what it attempts to execute.
RESET
New pass
Password loaded and ready to blow up the app.
Continue through to crash, and its the same 1211 execution.
Looking at the login function, looks like 451c states access granted.
RESET
New Password (address location reversed for endianness)
Continue through until right before the return, where theoretically, it should jmp 451c
Success!
...
Well, I was able to write access granted to screen, but it doesn't look like it actually unlocked the door. It just crashed.
So I'll take a look through the disassembler for something else. Maybe there is an unlock door function elsewhere.
Looking through the stack I see nothing of note...
So I reset, and break right before the jump to 451c, maybe it looks different then?
RESET
Continue, input same password, but break at 452a and look around.
But it looks the same... I do not see a function that will unlock the door.
I take a closer look at the conditional_unlock_door function, and I don't see anything called that might reference an "If passed go here instead" type of call or jmp.
I look through the live memory dump, and I don't see any memory space NOT referenced in the disassembly view, except this little section here...
Which BDBDBDBDBD doesn't seem to useful to me?
So now I'm thinking I need to go back and re-read the manual, or maybe go reference Cusco and see what command was executed to unlock the door, put that command in my buffer, then jmp to my passwords memory space to execute that command? Maybe I missed something, unlocking isn't coded into this thing!This sort of explains why I do not see an unlock command. I'm going to try my Cusco idea, MAYBE the unlock door command is small enough to fit in my buffer, and I can jump to it.
So I head over to Cusco, and unlock door looks like this:
I compared the int function in Cusco to the int function of Whitehorse. I think this may work. If I push \x7f onto the stack, then call int, then incd sp and ret, ALL inside of my password, then execute my memory space? Let's hope I get endianness correct. I need to note the different memory address of int, change my pointer to 3630 where my password is stored, and fill the excess space with buffer so I properly overflow.
I THINK this will do it: 1230007f12b0324553214130909090903036
So I can get my pointer to my password:
Except the instruction is not push \x7f, looks like I got endianness wrong.
So reset, new password: 3012007f12b0324553214130909090903036
That looks much better! I think, I'm not sure about the endianness of 007f or 7f00. Oh well, step next.
The very next instruction is butchered.
OK reset, forget endian except for the memory pointer. New password:
30127f00b012424521533041909090903036
Step through my instructions:
Crap.
I forgot the NEW location of int in this program. I jumped to the middle of int not the beginning.
RESET
New password: 30127f00b012453221533041909090903036
Step through my instructions again:
Endian's big brother was definitely the better person. Reset, and little endian the memory address of int.
RESET
New Password: 30127f00b012324521533041909090903036
Step through again:
Run through int as normal.
Success, door unlocked.
Notes:
This one is the new favorite for me. I'm still a little confused as to when to use little endian and when to not use it. Basically, I guess if I should use little endian or not, but it seems I always guess wrong. I wish I knew the hard and fast rules so I could get it right the first time.
However the sending your own shellcode into the buffer is definitely a nice touch to the challenge. I got the idea from WAAAAAAAAY back in ~2005 when I played on Hackthissite.org. They had a web challenge with LFI to get the flag, the very next challenge had the LFI fixed; however, you could go back to the previous challenge, use the LFI vulnerability to grab the flag for the next challenge too. I was debating even trying going back to Cusco and referencing the door unlock function, thinking it would be a different unlock code for this challenge, or it wouldn't work, excuse excuse excuse, but I am glad I tried it. The win felt great.






















0 comments:
Post a Comment