Security_RNRF

0x43. 본문

LiveOverFlow/Binary

0x43.

RNRF 2021. 11. 3. 01:15

43. Introducing Weird Machines: ROP Differently Explaining part 1 - bin.0x29

: The topic of this video is very special to me because it's the slogan of this channel.
-> "explore weird machines". So in this video I want to introduce what a weird machine is and use it to explain return oriented programming.
-> But let's start from a clean slate.
-> Please forget the term return oriented programming and weird machine. And let's start with something else.

: I really want to show you this really weird programming language I made.
-> It's a really terrible language.
-> But let me show you some example programs.
-> Here is a simple hello world. In this programming language you first have to initialize the program, and then you can start writing actual instructions.

Ex.1): cat helloworld.weird
INIT

SET VAR:4 “Hell”
STORE VAR:4 MEMORY:1
SET VAR:4 “Wo”
STORE VAR:4 MEMORY:2
SET VAR:4 “rld!”
STORE VAR:4 MEMORY:3

SET VAR:DST MEMORY:1
SET VAR:SRC 0
PRINTF

EXIT

-> Picture



-> So here we SET the variable four to the string “Hell”. And then we store that variable four in memory location 1.
-> Then we set variable four to “O SPACE WO”, and store variable four again in memory location 2.
-> And lastly we set the variable four to “rld!” and store that value in memory location 3.
-> Next we want to print it.
-> To do that we have to prepare the two parameters for “printf”.
-> The fist parameter, that will be the variable, is set to the memory location 1.
-> The memory locations are continuous memory, so printing from location 1 will print the whole string.
-> And the second parameter of “printf” will just be set to 0.
-> It's just a “printf” of the “helloworld” string.
-> No “printf” format modifiers and parameters here.
-> And at the end we “exit”.
-> All in all a bit ugly language, but makes somewhat sense, right?

: Let's run this program!
-> python compile.py helloworld.weird helloworld.out

-> First we have to compile it with this python compile script that I wrote.
-> python “helloworld.weird”, that's the source code, and the name of the outfile, so “helloworld.binary”.
-> Let's quickly look at the produced binary in the text editor.
-> vim helloworld.out
(2:11)
-> It starts off with some readable characters, “1”, “123” and a lot of “AAAAAAA…”.
-> But we also can find our “Hello world” in there. “HELL o WO RLD”.
-> The other values are just jibberish.
-> But let's run it! To run it you have to simply “cat”, so print the binary file and “pipe” the output into the interpreter, called invoice.
-> cat helloworld.out | ./invoice

-> Okay, I know the output is really confusing.
-> But that's just part of the weird invoice program. so just ignore that invoicing menu.
-> Because all the way down here at the bottom we can find our output! “HELLO WORLD!” Awesome!

: Let me show you some other examples. This here is a simple “ECHO” program.

Ex.2): cat echo.weird
INIT

READSTRING MEMORY:1
SET VAR:DST MEMORY:1
SET VAR:SRC 0
PRINTF

EXIT

-> Picture



-> It reads a string from standard input into memory location 1.
-> And then also prepares “printf” with the memory 1 location to print that string.
-> Again we can try this out by first compiling it, and then we have to output the binary and pipe it into the input of the invoice program.
-> python compile.py echo.weird echo.out

-> But not only that, we should also execute cat so the input doesn't close and we can send more input that we type to the program.
-> (cat echo.out; cat) | ./invoice

(3:23) Hello LiveOverflow(input)

-> Just some linux commandline foo, don't about it.
-> But fact is when we execute this, the program waits for input, we can type something in, and the output is here!
-> It worked!!! and please, again ignore the invoice jibberish menu around it.

: Let's do another example. I'm really proud of this one.

Ex.3): cat sum.weird
INIT

READSTRING MEMORY:1
STR2INT MEMORY:1
SET VAR:4 0
ADD VAR:4+RESULT
STORE VAR:4 MEMORY:2

READSTRING MEMORY:1
STR2INT MEMORY:1
LOAD VAR:4 MEMORY:2
ADD VAR:4+RESULT

SET VAR:DST STRING:1
SET VAR:SRC VAR:4
PRINTF

EXIT

-> Picture(3:34)

-> This will read a string into memory location 1.
-> Then it will execute String to integer on that value.
-> So we have to enter a number.
-> The result, so the raw integer number will be in the result variable.
-> Then we initialize the variable four with zero, and add the result, so the number we entered to it.
-> Then we store that value into memory location 2.
-> Then we read another number as string and convert that string also to an integer.
-> Now we load the old value from memory location 2 back into variable four, and then we add the new converted integer in result to the variable 4.
-> And then we prepare printf, but this time we have two parameters.
-> The first one is of course a format string.
-> The programming language has a few hardcoded format strings like string 1 here.
-> And as the second parameter, we have our variable 4.
: Let's try it!!!
-> We compile the sum program. And execute it again with cat.
-> python complie.py sum.weird sum.out
-> (cat sum.out; cat) | ./invoice
(4:34)
23 # Input the first number
19 # Input the second number

-> Then we enter the first number.
-> Then the second number.
-> And we get the calculated sum output.

: Okay... you ask yourself probably what is up with this weird programming language.
-> Why am I showing this here?
-> Well... the only reason why I showd it was, because I need you to fully agree with me, this is a "programming language", right?
-> We can write programs, then we can somehow compile them, and then they get executed.
-> Simple... but also very weird looking.
: So let's have a quick look at the invoice program.
-> ./invoice
(5:10)
-> It's actually a regular simple “c” program.
-> When we just execute it alone we can for example add an invoice, enter an in euro and add a comment.
-> We can add a few more to just get a feeling for the program.
-> And can then select options like calculating the sum of all invoices.
-> Or we can just and exit.
-> After entering our name we get a nice list of our invoices.
: Soooo... wait... what? This is an invoice managment system?
-> So how can this program execute these other programs? wat? that doesn't make any sense?
-> Let's look again at the binary of one of our compiled programs.
-> vim helloworld.out
(5:51)
-> We know this is given as input to the invoice program, so let's just try to copy that.
-> And maybe we also run it with GDB. So run the “invoice” program.
-> gdb ./invoice
(6:00)
-> run

-> 
-> Then we select 1.
-> Add an invoice.
-> It asks for amount and we enter 123.
-> And then comes all theese “AAAAA…”.
-> Let's copy those and a bit more data at the end(BBBB).
-> BOOM! Segmentation fault? RIP, the instruction pointer(=RIP) is 42424242, so BBBB. We have caused a buffer overflow and overwrote the return pointer on the stack.
: Maybe you think now, ahh... this was just a buffer overflow, and our programs were just shellcode in assembler.
-> But nope! when you check the security flags you see that the non-executable flag is used.
-> checksec
(6:40) # NX: non-executable flag!
-> And looking at the memory layout you can also see that stack or heap is not executable.
-> vmmap
(6:46)
-> So how can we execute these programs even though we can't inject assembler as shellcode?
: To answer this question I would like Sergey Bratus to introduce the concept of weird machines from his talk "What hacker research taught me".
-> Lesson 2, is what I call "composition creates weird machines" parallel universes of computers.
-> Any complex system turns out to be casting mini shadows. and of these shadows only one is what you intended.
-> That is the development environment you work on.
-> Everything else is a weird machine. Whose instructions are actually combinations of your well designed features.
-> But it will run the attackers code.
-> And do exactly what we defined as undermining your trust assumptions.
-> Leading to behaviour that is entirely unexpected by the designer of the machine.
-> So think of stack overflows. Think of heap overflows which are a bit more interesting.
-> In each case you have a component of your actual machine that is executing instructions that the exploit crafted input can trigger.
-> That you did not intended to be executed in that fashion.
-> It's a whole universe of weird machines.
-> So exploitation is from that point of view, programming of that weird machine via crafted input most often.
-> And so here is one case study from 1997 when a technique called return-into-libc was invented to what the academia now calls return oriented programming.
-> And it took about 10 years to propagate.
-> All the work in these series of techniques is done by code fragments already present in the trusted code.
-> So no new untrusted executable code is introduced.
-> No new attacker code is introduced. All the manipulation.
-> All the activity is done by parts of the machine that you thought were your friends.
-> Well no, they are traitors, lying and wait.
-> In 2008 when academia finally got a firm understanding of this brand of technique, it was dubbed, malicious computation, to distinguish it from malicious code - which is what your exploit (assembly shellcode) is.

: The concept of weird machines is so beautiful and that realization was very impactful to me.
-> Thus it became the mantra ar slogan of my channel.
-> Return Oriented Programming is one example of using a weird machine.
-> And the “weird machine” we have here is implemented in the “invoice” program.
-> The “invoice” program implemented one intended machine, the invoice management system, but also implemented an endless amount of weird machines due to a stack buffer overflow.
-> The developer has crafted a weird machine without even knowing it.
-> A weird machine so powerful that it can execute basically anything.
-> So powerful we can create a programming language that only runs on this single weird machine.
-> Isn't that amazing? And remember, we do this WITHOUT injecting arbitrary assembler instructions - we don't have shellcode here. We are using the technique of return oriented programming to achieve arbitrary execution. And it's so weird.
-> And it's so beautiful at the same time.

: In the next video I want to look closer at the weird programs that I have written, and what the compiler does, and how exactly this is executed.
-> And if you haven’t already guessed it, let me give you a small teaser, you could call these “instructions” actually “gadgets” *wink* *wink*.
-> So next video we will learn how return oriented programming works.
-> But in the meantime, please go watch the talks I have linked below and read the papers I have linked.
-> For me, they belong to the most important computer science and hacking or IT security papers.
-> https://www.cs.dartmouth.edu/~sergey/hc/rss-hacker-research.pdf

Ex.1): cat helloworld.weird
INIT

SET VAR:4 “Hell”
STORE VAR:4 MEMORY:1
SET VAR:4 “Wo”
STORE VAR:4 MEMORY:2
SET VAR:4 “rld!”
STORE VAR:4 MEMORY:3

SET VAR:DST MEMORY:1
SET VAR:SRC 0
PRINTF

EXIT

: python compile.py helloworld.weird helloworld.out
-> helloworld.binary

: vim helloworld.out
-> Shit print string…

: cat helloworld.out | ./invoice
(Tips. “invoice” is Interpreter)
-> “invoice” manual + Hello World!

Ex.2): echo.weird
INIT

READSTRING MEMORY:1
SET VAR:DST MEMORY:1
SET VAR:SRC 0
PRINTF

EXIT

: python compile.py echo.weird echo.out

: (cat echo.out; cat) | ./invoice

Ex.3): sum.weird
INIT

READSTRING MEMORY:1
STR2INT MEMORY:1
SET VAR:4 0
ADD VAR:4+RESULT
STORE VAR:4 MEMORY:2

READSTRING MEMORY:1
STR2INT MEMORY:1
LOAD VAR:4 MEMORY:2
ADD VAR:4+RESULT

SET VAR:DST STRING:1
SET VAR:SRC VAR:4
PRINTF

EXIT

: python compile.py sum.weird sum.out

: (cat sum.out; cat) | ./invoice

: Why show weird language???
-> Another program was run as an invoice program.

: gdb ./invoice
-> 1
-> 123
-> AAAAAAAAAAA…
-> segmentation fault (= Error)

: checksec
: vmmap

'LiveOverFlow > Binary' 카테고리의 다른 글

0x45.  (0) 2021.11.03
0x44.  (0) 2021.11.03
0x42.  (0) 2021.11.03
0x41.  (0) 2021.11.03
0x40.  (0) 2021.11.03
Comments