← All talks

Highway 64 | Michael Gonzalez

BSides Sydney43:0811 viewsPublished 2025-02Watch on YouTube ↗
About this talk
An introduction to the basics of 64-bit Windows binary exploitation. understand the difference between using 32-bit binaries and 64-bit versions. Difference in their architecture, function calling conventions, and etc. Finally a demo on buffer overflow on a 64-bit binary.
Show transcript [en]

our next speaker is Michael Gonzalez he is a security consultant at RSM Australia he previously worked as a computer programmer for a decade before shifting his career to infosec presenting his talk titled Highway 64 please welcome Michael Gonzalez than you go on uh let me fix this check my

notes so uh hi everyone first I want to thank everyone who are here for my talk and I hope you'll be able to learn something from it so uh the reason for my talk that came about is I want to share some of my experiences when doing thck client application testing and yeah most most of the testing that I did with my previous clients were like in graphical user interface form or like uh uh desktop application form and not in like a console application from that you can find mostly on

ctfs so the UN for the stock is yeah who am I and uh going to the introduction of what is binary exploitation uh address bus and data bus uh how how are the in memory CPU registers being used and the types of calling convention and how uh memory address are loaded into the CPU before they are being called next one will be the Shell Code uh what what are the types of Shell Code and uh how can we use them and finally the demo so who am I uh just what she said I'm Michael Gonzalez uh I work for RSM Australia I'm currently a security consultant previously you work as a computer programmer before shifting my

career into infosec so you can check my link QR code and my Discord is uh infos Noob so what is uh binary exploitation so basically binary exploitation is exploiting the current logic or vulnerabilities that exist within the uh the binary itself so this could be like uh input missing input validation flows uh logic logic control flows and yeah uh just taking advantage of the current flows of the binary address bus and data bus so that the CPU has two types of of uh address or Channel bus typically they come in pairs we have the uh the address itself and and the the data that much as the uh address next one so the CPU has like a

in memory builtin in memory registers and uh for uh 32bit we have like can store up up to four bytes while the 64bit can store up to uh 8 bytes so let me show you a demo of that one

so this one's for the 32 bit let's play

it this one's for the for the 30 a

bit so this one for the uh 32bit as you can see on this side these are the CPU registers or we call it just built-in CPU memory uh which which uh which is faster than the like normal memory that we have in our computers or like the SSD or something so as you can see uh the maximum or the bites the capacity that it could hold compared to a 64bit which which is like almost uh doubled and one so I have the CPU registers next we have the standard uh uh calling convention so for most uh 32-bit uh the client applications we we have the C declaration standard call or the standard call declaration while on the 64bit most most

of this uh 64bit uh use use the fast call calling convention and here we can see the a function just a simple function my function and how it's being called in the main function so let's show a demo of this one and let's see how I gold okay let's go back

here so I will just create a simple application or is it it okay desktop yep sweet simple one Windows

desktop okay so this is the default one now let's plug in our sample

function

copy so where's the main function that's a main function let's Bas it

here okay know

and let's let's call it when we're going to exit the application so we can put it here and just save it so first we're going to compile it on a 32bit

rebuild it's save there and then let's compile it on a

64bit copy that

there yep let's go to the 30 to bit first

and where's our 32 bit

debugger okay so that's our 32 bit let's just so let's go to the memory Map and find where's the entry point of our application so this the one and for the most of the instructions will be on this section the text one and that's where we're going to go okay so this is the entry point for our application and just let's just look for the function that we made so this one and let's put a break point on that so it's going to break there before continues and pass and just let's just click play play so this just the standard application so it's going to break when we click this okay so we hit the break

point so as we said on the slide where's that slide there you go so uh when calling a function uh the parameters are like stored on the on the stock straight away and let's see

this so you can see here this is the stock so those are the values for the parameter called and now let's go to

the 64

bit 64 B okay let's go to the memory map tab find the entry point for this one so there it is just follow ass symol and let's look for the function that we just made this one and let's just put a break point on that

one okay so uh on the slide we have uh for 64bit the the parameters are stored within the registers and some on on the stock so first we we store it in the rcx then RDX then R8 and R9 then the rest are in the stock so let's see if it's true on this so for this one let's play it first and should hit the break point there okay we hit the breako on the function that we made then let's check parameters are being passed here here R8 and R9 and as you can see we have this five and six on the stock so let's for so that's for the standard calling convention for a 64bit and a

32bit next one so the canonical address for 32bit and 64bit are are different so for 64bit we we don't consume all the the addresses that are available for you but we only uh we we leave uh we only have what's this like two bytes off of the given capacity for the canonic calendar so we can show this one in the demo here so we will try to overflow the IP for a 32bit and for a 64 bit and let's see if it's uh true that these ones are not being follow see for this

one we have the 32 bit

okay for this one we uh we'll just chck in some uh random string we'll be using lots of a on this one we'll be using like 1,000 a and let's see what happens s

just just type in some here and see if hit the break point here so as you can see here in the debugger we we just uh like cheuck in some random letters and you can see the instruction pointer was uh been uh overflown by like lots of Ace like the whole instruction pointer was uh overfilled and let's see on the 30 uh

64bit is

that okay uh so as you can see there are registers that have been overwritten by letter A but it didn't overwritten the instruction pointer because it doesn't follow the canonical address for a 64bit application

so uh what is a Shell Code a shell code is just a piece of uh assembly instructions that could be plugged in into a vulnerable uh binary application so these are the different uh shell code forms or example so we have on the left side the assembly code so these are the op codes and on this side we have the actual assembly code and if we want to convert this assembly code into like a string or we could uh we usually uh escape the op code using the back SLX to indicate that it is a hex and some of some Shell Code are in just plain up code form so most of the uh when doing a binary exploitation

we we would be using this kind of uh shell code form and we have the final one the demo

so we have the 64bit binary application there and we have the 32bit binary application

so we'll open the application make sure it's working just types nor 7 and let's type in the correct username and the wrong password failed now let's type in the correct password should work so simple loging for and let's copy that and let's open it in our

debugger let's just paste the directory and make sure

it's yep we just play it make sure it's running and let's just type some random stuff there now we're going to copy just a long string which is uh 100 characters of letter A again we're just going to paste it the username

and we hit a break point because it uh overwritten some of the registers and the next instruction pointer which is not a canonical address so this would be the next instruction and it couldn't load it to the rip so it just stops there and some registers had been overwritten as well so we have so that's that's where the last uh instruction so we're going to put a breako on that one and we'll restart and we we want to make sure that we hit the break point and just we're just going to paste the letter A again

and this one we going to so we're going to be using the ERC plugin which is available for uh ex64 debugger and it's free so it's yeah it's just going to generate mix of alpha numerical characters instead of letter A so at this point we want to find the exact overflow of the the username so we just going to copy that and I just pasted it there just a whole straight

string and we're going to paste it in the username and should hit the break point

again yep we hit the break point and we're going to check which part of the

string so this this is the part where the last string was uh overflowing so so that one we need to convert it to uh asky form and we're going to search it in the new memory so I I I just use any online like conversion tool line just use Rapid tables and convert it to aski and we're going to copy that and we're going to search that in the dbar

so again we would be using the ERC plugin to search for the string that was

overflow so at this point it says the string overflows at uh 872 so G yeah just take that now and now we know it's on 872 and we're just going to verify and add some different characters so we're going to add B on that one and we should uh check it in the debugger and should reflect on the debugger as well

so we're going to paste that

one and yep we hit the break point and as you can see uh the equivalent of B is 42 42 so yeah so now we know it's working we know that we could overwrite the EIP next let's just restart it again and let's see what

happens now we're going to put letter C in front of the string and we're going to check if it's likewise reflecting on the debugger at this point we want to see where where the locations of the registers are being overflown so we could see which one we could use later so we hit the break point yeah we have the letter BS on the end of the string and as you can see the forces are reflected on the Rax and some registers as well so at this point we know that this one would would be the next instructions pass to the rip and we know that uh Rax as the letter c over written it r10 and R11 P so this

one we could like maybe just use Rax to jump into our next instruction like we call it gadgets that we could use so and to see on the next slide

so uh for this one we're going to insert our Shell Code on the 64bit binary We'll add a new section

just 1,000 space of a new section and let's call it my set and of course we need to uh make this uh section executable because that's where we're going to put our Shell

Code and let's just create a new one so we won't overwrite the old

one okay now we have the new section on just want to make sure it's working now that we have the new section we're going to put in our Shell Code in it so we going to look for our new section in the memory map so that's the name of our new application the text and as you can see on the end we have the my SEC new section just going to follow it in the D and we're going to copy our n o sled so basically this shell code is uh does nothing just an empty instruction so why are we putting this uh NP sled because we want to make sure that every time we overflow or exploit

the application if we land in any address of this binary we'll we will just like slide through to our next Shell Code so for the Shell Code I download it from uh exploit DB it's uh uh yeah two 205 by Shell Code and yeah we just copy that Shell Code and it's just a popup

calculator we just copy that Shell Code and we just space it after our n sled

insid and yep that's our Shell Code over there and we'll save it as a new executable so we want to make sure everything's checked here or you just could click SEL all and PCH and now let's add with shell cat okay now now we have our new section and we know that we have a the Shell Code in it we want to make sure that new section with the shell code is running

properly let's open the debugger and open that new application so at this point uh we want to check the shell code is running so I just like overwrite the [Music] the first instruction pointer to the Shell Code address or the new

section so yeah we're going to modify the RIP just pointing to the new section

okay now we know our Shell Code in the new section is

working one

okay now we just overflow it again and we we want to find which uh which part of the registers that we could use

so we're going to hit a break point again where the errors stopped and we we were just at this point we're just repeating what we did at the first one but this one we it's just with the new section and Shell

Code so we hit the break point point

there and we going to step into so you see the rip was overwritten by letter b and uh RX was over written as well so we're going to use uh the jump RX up code or Gadget so at this point we want to search the memory address of uh Rax because we're going to use that on the uh input

string we're going to search the memory where jump AR X is

and we have a like long list of available memory address that we could use for uh the jump RX the results are saved into a text file as well in the plugin section so we just going to open this file and just search it from there so we know that yeah done FF eer is the jump ax and we want to make sure those uh safety security settings are all false and I usually get the last available jump Rax memory address from that one and yeah just copy it over there and so at this point we we plan to jump to Rax and execute the Shell Code from there so yeah so we know the jump RX

memory address is working we we we want to put a break point there and we're just going to restart it and make sure it's working

yeah so we with the memory address we need to convert it into ask it again but in reverse because Intel CPUs store memory address in uh reverse order or what they call little Indian so now we converted the memory address to that one so that one is our jump Rax and we're just going to replace that instead of letter

B's so what's going to happen next here once we input this uh string it's going to load up that uh Rax address on the instruction pointer or the rip over here okay now we hit the break

point and it's just going to step and yep we with the RX instruction it's going to jump there and it should execute that string but it's not going to load it because it's not a canonical address going to fix that later

okay now next one is we're going to put some assembly code in front of the payload so for that one uh it's just a simple uh assembly instruction that's going to jump to our section address that we have created a which is the popup calculator

so we copy that assembly instruction again we're going to convert it into up code first then convert it into asky and going to paste it on the string

so that's the text code for the assembly

instruction and uh we're going to convert into string we need to convert that uh instruction to string Cu uh the payload that we used is string as well

yeah copy

that yeah I think there's something ISS with the copy and pasting here but yeah so we have the string form of the small assembly code that we made so that assembly code so we're going to put it in front of the payload so what we have here now is a a a complete payload that jumps to Rax rip executes Rax and it executes the uh simple payload in front of the string that jumps to our new section okay let's test it if it works so just going to paste it there just going to paste that whole string

there okay now we hit a break point so this one would be jump RX

and we I'm going to do a step into and that was our code that jumps into our new section and yeah you just step up into it and make sure it's there and yeah we have the popup calculator working

so at this point we want to we want to make sure it works without the debugger just the application itself and there you go calculator executed on a overflow on the username so yeah so we we we used a uh jump Rax and then from jump Rax we we we we created a simple small uh assembly code that jumps into our new section and our new section has the Shell Code in it so yeah so uh you you might be asking oh you could just like have put the the Shell Code straight away on the string and and and the Rax on the end but uh just this one another solution that I just presented so yeah uh thanks everyone

less than 15 and yeah hope you enjoy