Questions about this topic? Sign up to ask in the talk tab.
Classes/Logs/2012/September/21/00-01
From NetSec
Revision as of 02:22, 21 September 2012 by Chantal21I (Talk | contribs)
00:21:21 <hatter> Ok so 00:21:37 <hatter> today we'll go over some intermediate shellcode techniques 00:21:44 <hatter> xo: I'll ping you after class about that :) 00:21:54 <hatter> So, `intermediate', 00:21:58 <hatter> this is going to involve some 00:22:02 <hatter> filter bypass stuff 00:22:26 <hatter> Existing character filters are sometimes alphanumeric, unicode, strtoupper/tolower, 00:22:33 <hatter> sometimes even english filters 00:22:39 <hatter> will get in the way of shellcode injection 00:23:25 <hatter> additionally, we'll talk about a few ways to utilize shellcode in circumstances with incredibly small buffers 00:24:51 <hatter> I've already done a couple of papers on printable shellcode, available at http://www.blackhatlibrary.net/Alphanumeric_shellcode and http://www.blackhatlibrary.net/Ascii_shellcode 00:25:22 <hatter> there are multiple ways to write unicode-proof shellcode 00:25:37 <hatter> The method I favor is using all uppercase numeric printable characters 00:26:02 <hatter> as it has the least likely possibility of containing a character that will be filtered post-unicode conversion 00:26:13 <hatter> ALPHA3 by Skylined can let you do that - 00:26:23 <hatter> though, also requires a bit of experience to use it 00:27:22 <hatter> its also been proven possible 00:27:30 <hatter> to write shellcode in plain english 00:27:33 <hatter> although it gets pretty complicated 00:27:38 <hatter> it will get past an english language filter. 00:29:02 <hatter> www.cs.jhu.edu/~sam/ccs243-mason.pdf 00:29:14 <hatter> ^take your add meds before reading that 00:29:58 <hatter> we usually run into limitations here 00:30:12 <hatter> when we get to case conversions 00:30:26 <hatter> does anyone know the term for shellcode that can survive any type of case conversion? 00:31:22 <hatter> Not sure why, but its called "crunchy" shellcode. It was originally called this by xort from dallas 2600 years ago. 00:33:01 <hatter> Self modifying code is the principle behind nearly every character filter bypass technique 00:33:08 <hatter> in some cases, out of order code execution is used in stead. 00:33:44 <hatter> http://www.blackhatlibrary.net/Out_of_Order_Code_Execution 00:35:30 * tr0gdor ([email protected]) has joined #CSIII 00:36:08 * tr0gdor_ ([email protected]) has joined #CSIII 00:36:11 <hatter> out of order code execution can also sometimes be used during return oriented programming 00:36:27 <hatter> to obtain segments of otherwise procedural (non functional) code as functional code 00:37:43 <Atlas> hi 00:37:46 <hatter> moving on to talking about space limitations now, unless there are questions about bypassing character filters. 00:38:20 <hatter> I'll give you guys a minute or two 00:38:53 * guitarpie ([email protected]) has joined #CSIII 00:39:28 * ackit_ ([email protected]) has joined #CSIII 00:39:47 <hatter> so, moving on to space limitations 00:40:22 <hatter> there may be instances in which you don't have the necessary space to fit shellcode into your overflow 00:40:32 <hatter> who is already familiar with the term second-order injection? 00:41:28 <hatter> second order injection is used when confronted with space limitations - 00:41:41 <hatter> Essentially, code is placed into a buffer that is not vulnerable 00:42:11 <hatter> and then when the vulnerable buffer is overflowed, it executes code placed in the original buffer (the not vulnerable buffer). 00:42:54 <hatter> these buffers are usually adjacent in some way in memory, either with a predictable offset, within the same stack segment, or a mixture of the two 00:43:45 <hatter> one technique for finding the code in situations where the code resides within the same buffer and the offset cannot be found 00:43:50 <hatter> includes something called an egghunt 00:43:58 <hatter> I did something very similar 00:43:59 <hatter> for 00:44:05 <hatter> the ELF parsing routine 00:44:12 <hatter> when locating the base pointer of the binary 00:44:43 <hatter> an egghunt is a small piece of code capable of navigating its own buffer until a location containing the desired value is located 00:45:00 <hatter> at which point, the egghunt may jump to the code, or invoke it like a function 00:45:07 <hatter> in other cases, the egghunt may simply return to the code. 00:45:49 <hatter> I guess while we're discussing it 00:45:53 <hatter> since we haven't gotten many questions 00:45:54 <hatter> we can kinda go over 00:45:57 <hatter> return oriented code 00:46:03 <hatter> call stacks 00:46:06 <hatter> and the stack itself 00:46:12 <hatter> who here knows how a call stack works? anyone? 00:46:20 <xo> < 00:47:27 <pseudo> it is implemented like a linked list if im not mistaken 00:47:41 <xo> its implemented like a stack 00:47:42 <xo> :P 00:47:53 <hatter> its implemented similarly to a linked list 00:47:55 <hatter> he's right 00:47:59 <hatter> in terms of what it looks like 00:48:01 <hatter> within the stack 00:48:03 <hatter> it looks about the same 00:48:04 <hatter> as a linked list 00:48:08 <hatter> its just an array of pointers 00:48:20 <hatter> but 00:48:21 <hatter> more importantly 00:48:52 <hatter> when the "call" instruction is executed 00:48:56 <hatter> \xe9 00:49:02 <hatter> (32 bit intel) 00:49:17 <hatter> it pushes the return pointer 00:49:18 <hatter> to the stack 00:49:21 <hatter> then jumps to the location 00:49:26 <hatter> when ret is executed 00:49:28 <hatter> \xc3 00:49:30 <hatter> (32 bit intel) 00:49:40 <hatter> it pops the most recent register-sized value from the stack 00:49:48 <hatter> then jumps to that location 00:49:58 <hatter> this is the reason that an overflow exists* 00:50:23 <hatter> * (only if you get super technical, can you blame it on intel, for example, MIPS does not store the return pointer in the stack) 00:51:21 <hatter> Now 00:51:24 <hatter> that means if I 00:51:26 <hatter> push pointer 00:51:26 <hatter> ret 00:51:31 <hatter> its about the same as jumping 00:51:33 <hatter> to that location 00:52:22 <hatter> (this is what happens during the execution of an exploit payload) 00:52:31 <hatter> that said, 00:53:03 <hatter> a call stack is simply a sequence of data that forms a logical chain of functional programming with address indexing 00:53:32 <hatter> if you 00:53:33 <hatter> push pointer 00:53:35 <hatter> push pointer 00:53:36 <hatter> ret 00:53:44 <hatter> when the first set is done and it returns 00:53:49 <hatter> it will return to the first pointer pushed 00:54:00 <hatter> you could even make a recursive function using this 00:54:03 <hatter> type of programming 00:55:07 <hatter> the call stack is what is located within the stack - 00:55:19 <hatter> payloads which bypass aslr and nx 00:55:21 <hatter> are not actually shellcodes 00:55:24 <hatter> they are call stacks 00:55:35 <hatter> some of them utilize out of order code execution 00:55:37 <hatter> some of them dont 00:55:38 <xo> they leverage existing executable code 00:55:45 <hatter> ^ 00:55:49 <hatter> Out of .text segments 00:55:51 <hatter> of binaries. 00:55:52 <xo> aka "gadgets" 00:56:00 <hatter> These are already marked as executable by the processor 00:56:21 <hatter> and therefore nx does not apply to them- or the call stack itself 00:56:29 <hatter> thus the problem of "ROP" based shellcode 00:56:35 <hatter> and the fun we get to have 00:56:53 <hatter> xo: you got some random 00:57:00 <hatter> rop shellcode handy? 00:57:13 <xo> not rly 00:57:17 <xo> theres prolly some in BL2 00:57:22 <hatter> Yea 00:57:23 <hatter> there is 00:57:25 <hatter> tons 00:57:27 <hatter> actually 00:57:29 <hatter> lol 00:57:35 <xo> everything cept java prly 00:58:24 <xo> you should explain a little abt gadgets, hatter 00:59:15 <hatter> well 00:59:17 <hatter> there's 00:59:20 <hatter> in-line (in order) 00:59:22 <hatter> and out of order 00:59:24 <hatter> gadgets 00:59:32 <hatter> in-order gadgets are things like 00:59:39 <hatter> placing pointers to arguments within the stack 00:59:48 <hatter> andthen placing your function pointer 00:59:50 <hatter> in the call stack 00:59:54 <hatter> so when ret is executed 00:59:59 <hatter> it invokes a function with parametgers 01:00:02 <hatter> *parameters 01:00:03 <xo> yeah 01:00:06 <xo> that wont work on x64 tho 01:00:06 <xo> afaik 01:00:11 <hatter> Yea it will 01:00:12 <hatter> its just 01:00:14 <hatter> annoy 01:00:15 <hatter> as fuck 01:00:19 <xo> isnt the calling convention different? 01:00:27 <hatter> yes but its still stack based 01:00:38 <hatter> its a register-order thing 01:00:39 <hatter> actually 01:00:40 <hatter> :3 01:00:45 <hatter> anyway 01:01:09 <hatter> out-of-order gadgets may or may not contain arguments however 01:01:16 <hatter> they are not clearly marked as functional code 01:01:18 <hatter> within the binary segment 01:01:30 <hatter> the binary may not have even been originally intended to be parsed that way 01:01:32 <hatter> for example, 01:01:40 <hatter> push 0x6a6a6a6a 01:01:42 <hatter> "hjjjj" 01:01:51 <hatter> pop %eax 01:01:54 <hatter> "X" 01:02:19 <hatter> normally, those would set the value of "eax" to "6a6a6a6a" or 'jjjj' 01:02:20 <hatter> however 01:02:26 <hatter> if you return to say, 4 bytes from start 01:02:29 <hatter> that last "j" there 01:02:37 <hatter> it turns into push byte 0x58 01:02:44 <hatter> (push 'X') 01:03:03 <hatter> so, simply because the assembly 01:03:06 <hatter> is not within the binary 01:03:07 <hatter> does not mean 01:03:10 <hatter> that the machine language 01:03:14 <hatter> is not in the binary. ;) 01:03:50 <hatter> and that's "out of order" gadget programming 01:03:54 <hatter> is returning to code out of order 01:04:06 <hatter> xo: I can help you with rop chaining on x64 if u want 01:04:07 <hatter> lol 01:04:09 <hatter> that would be fun 01:04:27 <xo> well iirc 01:04:32 <xo> arguments go in regs 01:04:38 <hatter> thats for 01:04:38 <xo> so you need gadgets to get shit off the stack & into regs 01:04:40 <hatter> syscalls 01:04:42 <hatter> but 01:04:43 <hatter> also 01:04:48 <hatter> one other major thing 01:05:05 <hatter> the stack frame 01:05:08 <hatter> has certain segments 01:05:10 <hatter> auto-converted 01:05:11 <hatter> to registers 01:05:14 <hatter> when return is called 01:05:16 <hatter> due to things like 01:05:19 <hatter> ret $0x16 01:05:21 <hatter> rather than just 01:05:21 <hatter> ret 01:05:25 <hatter> so depending on 01:05:33 <hatter> your ret 01:05:35 <hatter> getting sploited 01:05:39 <hatter> you'll have a frame 01:05:44 <hatter> containing some registers 01:05:46 <hatter> :3 <pre>