(19:08:23) DirtyBit: I just do not get sparc arch (19:08:31) DirtyBit: no matter how many times I read through it (19:08:58) John: what's tripping you up? :> (19:09:04) DirtyBit: the stack fram e construct (19:09:25) DirtyBit: nothing explains how o0-7 become i0-7 (19:09:51) John: save and restore do that i believe (19:09:59) DirtyBit: yeah (19:10:00) John: (it's been 5 years since i did much sparc programming) (19:10:01) DirtyBit: I know (19:10:05) John: hehe (19:10:06) DirtyBit: ah crap (19:10:10) DirtyBit: everyone says that (19:10:12) DirtyBit: hehe (19:10:28) DirtyBit: but I don;t get how it happens (19:10:31) John: well, you're supposed to settle for that answer :p (19:10:36) DirtyBit: never (19:10:38) DirtyBit: :) (19:10:54) John: i think there's a buffer (19:10:55) John: er (19:11:18) John: lemme google real quick (19:11:23) John: forget the basic names for things :p (19:11:27) DirtyBit: like reading howto bof on sparc is universally unhelpful too (19:11:36) DirtyBit: I can send you the pdf I am looking at (19:12:03) DirtyBit: http://www.sparc.com/standards/psABI3rd.pdf (19:12:26) DirtyBit: that explains it but my mind just doesn't seem to want to wrap around it (19:13:03) John: i think the register windows just shift over 128 bytes (19:13:08) John: so that o becomes i (19:13:10) John: or vice versa (19:13:15) DirtyBit: hrm (19:13:24) DirtyBit: I need pictures I think (19:13:31) John: imagine there's like 1k of registers (19:13:33) DirtyBit: gonna draw this out (19:13:36) John: and you have a window into them (19:13:37) DirtyBit: k (19:13:44) John: and the window moves forward and back (19:13:56) DirtyBit: ah (19:14:06) DirtyBit: that makes a bit of sense (19:14:25) DirtyBit: so by just moving sp o becomes i (19:14:42) John: yeah.. it's really completely unrelated to the stack (19:14:46) John: it's all in magic register memory (19:14:55) John: it uses the stack as an afterthought when it has to (19:15:05) DirtyBit: so ultimately what I am trying to undertstand here (19:15:22) John: basically the stack just has to have enough space available at any given point for the register windwos to be saved there (19:15:26) DirtyBit: is where is the saved return addr relative to local vars (19:16:04) DirtyBit: I mean I sort of understand that when you bof you are actually overwriting your callers saved addr (19:16:09) John: ok (19:16:10) John: yeah (19:16:11) DirtyBit: so the addr of callers caller (19:16:14) John: this is the tricky part (19:16:17) John: that no one explains (19:16:21) DirtyBit: exactly (19:16:23) DirtyBit: :) (19:16:27) John: i don't know for sure (19:16:35) DirtyBit: tried looking at this in debugger on sun box and failed (19:16:37) John: as in i havent read the kernel source (19:16:38) John: but (19:16:58) John: i think what happens is that whenever the the kernel switches to your code (19:17:03) John: er (19:17:06) John: say your code is running along (19:17:16) John: a() calls b(), b() calls c() (19:17:20) DirtyBit: k (19:17:25) John: the stack pointer will be advanced (19:17:34) John: but all the information will be kept in the register windows (19:17:40) John: and not really on the stack (19:17:59) John: now ssay in function c(), you run out of cpu time (19:18:05) John: and the kernel scheduler switches to anotehr process (19:18:09) DirtyBit: right (19:18:17) John: then, it will take the contents of the 3 or so register windwos, and write them to the stack (19:18:37) John: now, later on, when it restores the context (19:18:51) John: it just fills in one register window (19:18:56) John: so when that funciton returns (19:19:03) John: there will be a register window underflow condition (19:19:12) John: which is where the kernel reads from the stack (19:19:30) DirtyBit: not sure i understand that (19:19:50) John: there's room to track like 5 or 6 function calls in the register window (19:20:09) John: if you call more, it has to write some of it to the stack to free up register window space (19:20:12) DirtyBit: alright so look at register window structure then? (19:20:17) DirtyBit: ah (19:20:23) DirtyBit: ok that makes more sense (19:20:31) John: and if you return multipel times (19:20:34) DirtyBit: so you are actually overwriting 5 func back (19:20:39) DirtyBit: funcs (19:20:42) DirtyBit: or 6 (19:20:44) DirtyBit: or w/e (19:20:48) DirtyBit: damn (19:20:53) John: yeah, in practice you don't ahve to do that (19:21:02) John: because (19:21:07) John: so when there's a context switch (19:21:12) John: and it comes back (19:21:17) John: it only has one register window populated (19:21:42) John: so it will read from the stack for the function that called your vuln function (19:22:05) John: so, it would be like (19:22:13) John: a() -> b() (19:22:21) John: b has char[1024]; (19:22:23) John: you overwrite it (19:22:34) John: er wait (19:22:35) John: hehe (19:22:46) John: there's a context switch (19:22:50) John: then you overwrite it (19:23:00) John: then you return (19:23:13) John: the register window is empty, so it reads off the stack (19:23:17) John: and pulls in your evil value (19:23:23) DirtyBit: ah (19:23:44) John: i've actually had exploits where i needed to create load in order to generate a context switch at the same time (19:23:49) John: i mean at the right time (19:24:00) DirtyBit: wow thats wierd (19:24:01) John: doing like ping -f 1.2.3.4 (19:24:04) DirtyBit: haha (19:24:06) John: and running the exploit in an infinite loop (19:24:07) John: basically (19:24:08) John: hehe (19:24:09) DirtyBit: pretty awesome (19:24:11) John: find / -ls (19:24:12) John: hehe (19:24:35) John: so yeah, no one talks about that because it's hard :p (19:24:41) DirtyBit: haha yeah (19:24:42) John: i never verified this 100% (19:24:49) DirtyBit: thats why i want to understand it (19:24:51) John: but i'm pretty sure it works like this or very similarily (19:25:09) DirtyBit: you know of a good book? (19:25:19) John: you'd want to look for the register window trap handler (19:25:26) John: i think (19:25:29) John: and then kinda grep from there (19:25:33) DirtyBit: k (19:25:35) John: no, havent read a book on it (19:25:47) DirtyBit: there is like a sparc manual v8 (19:25:53) DirtyBit: or something but I dunno if its good (19:26:10) DirtyBit: no idea why I decided to figure this out (19:26:15) DirtyBit: heh (19:26:21) DirtyBit: but I have become obsessed (19:26:24) John: http://www.cs.unm.edu/~maccabe/classes/341/labman/node11.html (19:26:25) DirtyBit: :/ (19:26:27) John: that has some pictures (19:26:28) John: but they kinda suck (19:26:31) DirtyBit: ph sweet (19:26:36) DirtyBit: I like pics (19:26:50) DirtyBit: tex makes my head hurt (19:26:52) DirtyBit: text (19:26:53) John: haha. (19:27:43) DirtyBit: oh nice (19:27:53) DirtyBit: thats exactly what I was looking for (19:28:00) DirtyBit: thanks :) (19:28:05) John: hehe np (19:29:06) John: i guess practical rule of thumb is yeah, you overwrite the calling function's return address (19:29:30) DirtyBit: haha yeah like we knew that (19:29:43) DirtyBit: and were trying to figure out ow it works (19:29:53) DirtyBit: and it was confusing the hell out of us (19:29:57) John: yeah :> (19:30:10) DirtyBit: because that would mean your own ret addr is below local vars (19:30:18) DirtyBit: which makes 0 sense (19:30:24) John: nonono (19:30:29) John: yeah it's not that at all (19:30:35) DirtyBit: yeah I get it now (19:30:39) DirtyBit: kind of at least (19:30:46) John: you overwrite the place where your return address would be (19:30:55) DirtyBit: but yeah when you are just going backward from that assumption (19:30:55) John: it's just not used because it's in the register window (19:31:18) John: yeah i can see how that would make it very confusing (19:31:18) John: heh (19:31:25) DirtyBit: :) (19:31:58) John: cool (19:32:02) John: http://www.cygwin.com/ml/ecos-discuss/2005-02/msg00304.html (19:32:08) John: My understanding of the context switch code is that when a switch needs to be made, the current thread's register windows are all stored into their reserved areas in the stack frames they belong to. This is done by the sequence of save instructions. This fakes a sequence of forward calls around the window ring. Unused windows will do nothing, occupied windows will generate a window overflow exception to store the registers. At the end of this the windows are all empty. On restore it is only necessary to load the first window, all the others will be restored using window underflow exceptions as the code returns up the stack. (19:32:34) DirtyBit: I love how everyone prefixes everything with (19:32:39) DirtyBit: "my understanding of" (19:32:42) John: hahah ayeah (19:32:42) DirtyBit: hehe (19:33:52) John: yeah basically the register windows are supposed to make everythign faster (19:34:04) John: and the stack is meant to be the backup plan (19:34:22) John: but there's tons of context switches (19:34:30) DirtyBit: this makes x86 seem sooooo elegant (19:34:35) John: hehe (19:35:12) John: ive always meant to go back (19:35:28) John: and figure out how to exploit programs that do like an exit after only one return (19:35:34) John: because i'm sure it's possible (19:35:39) DirtyBit: hrrm (19:35:42) John: we just weren't smart enough back then (19:35:42) John: heeh (19:35:58) John: i mean, you used to get seg faults and bus errors (19:36:09) John: sometimes (19:36:26) John: maybe if you send singnals or something (19:36:33) John: you could get a sighandler frame on top of it (19:36:42) John: and get the context switch you need (19:36:43) John: dunno (19:36:51) DirtyBit: yeah it looks like something funky happens with signal handlers too (19:36:56) DirtyBit: another context switch (19:37:04) John: yeah one of the first overflows i found was actually in a signal handler (19:37:11) John: and if i didn't have the frame pointer 8-byte aligned (19:37:15) John: the entire system would crash (19:37:26) DirtyBit: :) (19:37:27) John: it was a bug in the solaris kernel (19:37:27) John: hehe (19:37:38) DirtyBit: thats kinda funny (19:37:50) DirtyBit: you ever figure out why it would crash (19:37:54) John: yeah, until you crash the wrong box :p (19:37:59) John: i asked casper dik (19:38:12) John: he just said it was a bug that was fixed (19:38:19) DirtyBit: how helpful (19:38:21) DirtyBit: :) (19:38:25) John: i guess the kernel code got a bus error (19:38:36) John: for doing an unaligned read (19:38:37) John: i dunno (19:38:45) DirtyBit: still if it makes an assumption like that about user code (19:38:56) DirtyBit: bad things (19:39:03) John: yeah, it was a special case because the kernel does magic around signal handlers (19:39:40) DirtyBit: yeah that pdf I inked you was talking about that (19:39:43) DirtyBit: high level though (19:39:45) DirtyBit: :( (19:40:53) John: you writing an exploit for that tttf thing or whatever (19:40:58) John: someone mentioned something like that to me earlier (19:40:59) DirtyBit: nah (19:41:16) DirtyBit: just randomly remembered trying to do something like this a few yrs ago (19:41:22) DirtyBit: and got curious about it (19:41:39) DirtyBit: honestly if I learn this well (19:41:49) John: also one thing to note (19:41:53) John: if you are in a debugger (19:41:59) John: and breakpointing/single stepping (19:42:06) DirtyBit: yeh? (19:42:08) John: the stack is going to be necessarily in sync with the register windwos (19:42:26) John: because there's a context switch or 2 with every instruction you execute (19:42:26) John: heh (19:42:30) DirtyBit: you will never see the switch yeah (19:42:37) DirtyBit: yeah I know (19:42:48) DirtyBit: they are sub instruction (19:42:50) DirtyBit: annoying (19:42:52) DirtyBit: :) (19:43:04) DirtyBit: thats why its so freaking hard (19:43:08) John: yeah :> (19:43:17) DirtyBit: and nothing makes sense in a debugger :( (19:43:20) DirtyBit: oh well (19:43:27) DirtyBit: it wouldn;t be fun if it was easy (19:43:42) John: yeah i mostly figured it out by writing a lot of exploits (19:43:54) John: and just getting them to work by luck and stubbornness (19:43:54) John: hehe (19:44:07) John: and eventually i sorta formed theories as to what was going on behind the scenes (19:44:37) DirtyBit: haha thats definately the hard way (19:44:49) John: yeah :> i didn't really know any better :p (19:44:53) DirtyBit: much easier to wait 7 years (19:44:57) John: hahah (19:44:59) DirtyBit: and ask the person who did it that way (19:45:01) DirtyBit: :p (19:47:09) John: you're overwriting a lot more saved registers and local variables than you do in a normal x86 exploit (19:47:20) DirtyBit: yeah (19:47:22) John: so you kinda have to do a bit more stack repair (19:47:32) DirtyBit: keeping everything working until the ret sucks (19:47:41) DirtyBit: well 2 rets actually (19:47:43) John: at the time, i would typically just pick some address that it could write to that had all 0s