PLanET ABhisEK
< June 2007
SuMoTuWeThFrSa
      1 2
3 4 5 6 7 8 9
10111213141516
17181920212223
24252627282930

Wed, 27 Jun 2007 12:01:00 IST

Linux Kernel Debugging: The Easy Way

Linux kernel debugging has always been a tough thing to do and requires pretty much a dedicated setup for regular effective debugging. But with the release of VMware 6, an inbuilt kernel debugger provided with it makes life pretty much easier in debugging the linux kernel for various requirements.

In case VMware 6 in Linux b0rks out for you with an error message:

neo@sauron ~ $ /opt/vmware/bin/vmware
/opt/vmware/lib/vmware/bin/vmware: symbol lookup error:
/opt/vmware/lib/vmware/lib/libvmwareui.so.0/libvmwareui.so.0: undefined
symbol: _ZN3Gtk13RecentManager11get_defaultEv
Try running VMware:
neo@sauron ~ $ VMWARE_USE_SHIPPED_GTK="yes" /opt/vmware/bin/vmware

To start with, do a regular installation of any GNU/Linux distro inside the VMware and recompile the kernel with debugging options enabled. My debug options looks something like this:

#
# Kernel hacking
#
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_UNUSED_SYMBOLS=y
CONFIG_DEBUG_KERNEL=y
CONFIG_LOG_BUF_SHIFT=15
CONFIG_DETECT_SOFTLOCKUP=y
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_VM=y
CONFIG_FRAME_POINTER=y
CONFIG_EARLY_PRINTK=y
CONFIG_4KSTACKS=y
CONFIG_DOUBLEFAULT=y
Make sure you have turned on Use of Frame pointers while compiling the kernel from "Kernel Hacking" option during the kernel configuration. This will help gdb in the debugging process.

To make VMware listen for debug connections to a TCP port in localhost just append the following line to your VMware Guest OS configuration file (.vmx):
debugStub.listen.guest32 = "1"
Now when you start your VMware guest OS, you will notice it is listening for a debug connection on 0.0.0.0:8832.
In order to make gdb do a source level debugging, you need to provide it with the entire linux source tree which was used to compile the Guest OS kernel including the uncompressed vmlinux binary.

So basically in the Host OS, you need to go to the directory where you copied the entire linux kernel source tree on which the Guest OS kernel was compiled and fire up gdb

BIG NOTE: I am *not* using the VMware console for accessing the Guest OS, instead I have logged into the Guest OS through SSH and do all the stuff required for debug/trigger actions. This is because when the debugger is attached from the Host OS to the Guest OS kernel running inside VMware, the kernel is interrupted by default untill you do continue in the debugger. In such scenario, if you are using the console, there is a high chance you will be trapped inside it since all keyboard actions will be trapped by the VMware and sent to the Guest OS kernel which is basically trapped by the debugger. In my case I got locked up and had to reboot.

neo@sauron ~/hacks/kern-debug $ gdb
GNU gdb 6.6
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu".
(gdb) file ./vmlinux
Reading symbols from /home/neo/hacks/kern-debug/vmlinux...done.
Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) target remote 127.0.0.1:8832
Remote debugging using 127.0.0.1:8832
[New Thread 1]
warning: shared library handler failed to enable breakpoint
0xc0102c58 in irq_entries_start ()
(gdb) bt
#0  0xc0102c58 in irq_entries_start ()
#1  0xc010104e in default_idle () at include/asm/irqflags.h:57
#2  0xc01010ab in cpu_idle () at arch/i386/kernel/process.c:192
#3  0xc010033e in rest_init () at init/main.c:432
#4  0xc03fa737 in start_kernel () at init/main.c:620
#5  0x00000000 in ?? ()
(gdb)
From here, you can do almost everything you would do in a normal user space application debugging.
(gdb) break do_execve
Breakpoint 2 at 0xc014f117: file fs/exec.c, line 1133.
(gdb) c
Continuing.

Breakpoint 2, do_execve (filename=0xc5ceb000 "/usr/bin/ls", argv=0xc015096e,
envp=0xc4dc6f9c, regs=0xc4dc6fb8) at fs/exec.c:1133
1133            int retval;
(gdb)
Looks pretty neat!

But I think its pretty much necessary to mention about the awesome User Mode Linux and the KGDB patch. Using those you can pretty much have the same debugging experience, just that you need to give some effort in setting up and maintaing the environment.

VMware 6 Kernel Debugger Reference: http://stackframe.blogspot.org

posted at: 12:01 | path: / | permanent link to this entry

Sat, 03 Mar 2007 17:45:00 IST

Snort DCE/RPC Preprocessor buffer overflow

Wrote an exploit after a long time.. nothing interesting, but a simple stack overflow but initially proved to be a bit hard to trigger.

Started by taking a diff of snort-2.6.1.2 and snort-2.6.1.3 which instantly revealed the vulnerable code.

diff -Naur snort-2.6.1.2/src/dynamic-preprocessors/dcerpc/smb_andx_decode.c
snort-2.6.1.3/src/dynamic-preprocessors/dcerpc/smb_andx_decode.c
--- snort-2.6.1.2/src/dynamic-preprocessors/dcerpc/smb_andx_decode.c
2006-12-05 00:08:36.000000000 +0530
+++ snort-2.6.1.3/src/dynamic-preprocessors/dcerpc/smb_andx_decode.c
2007-02-17 13:00:11.000000000 +0530
@@ -31,6 +31,7 @@
#include 

#include "debug.h"
+#include "bounds.h"

#include "snort_dcerpc.h"
#include "smb_structs.h"
@@ -61,39 +62,80 @@
 static void ReassembleSMBWriteX(SMB_WRITEX_REQ *writeX, u_int8_t *smb_data)
 {
     SMB_WRITEX_REQ temp_writeX;
-    unsigned int   smb_hdr_len = (u_int8_t *)writeX - _dcerpc_pkt->payload;
-    unsigned int   writeX_len = smb_data - (u_int8_t *)writeX;
+    u_int16_t      smb_hdr_len = sizeof(SMB_HDR) + sizeof(NBT_HDR);
+    u_int16_t      writeX_len = (u_int16_t)(smb_data - (u_int8_t *)writeX);
+    u_int32_t      check_len;
+    int            ret;
+
+    check_len = (u_int32_t)smb_hdr_len + (u_int32_t)writeX_len +
(u_int32_t)_dcerpc->write_andx_buf_len;

.
.
.
/* Mock up header */
-    memcpy(&temp_writeX, writeX, writeX_len);
+    memcpy(&temp_writeX, writeX, sizeof(SMB_WRITEX_REQ));
     temp_writeX.remaining = _dcerpc->write_andx_buf_len;
     temp_writeX.dataLength = _dcerpc->write_andx_buf_len;

After a bit of funtion call flow tracing and stuff.. got it right.
and oh, This helped a lot.

Thus, the following steps can reliably trigger the bug:
1. Send SMB TreeConnectAndX for \\X.X.X.X\IPC$
2. Send SMB NTCreateAndX
3. Send SMBWriteAndX + DCERPC Bind/Call with fraglength > payload (fragmented PDU)
4. Send SMBWriteAndX with a pretty large ( > 16 or so) padding containing ret and payload.
5. Bang! pwned.

For my testing purpose, I had nc listening on port 139 monitored by Snort 2.6.1.2 and the exploit connects to the port and blindly delivers the payloads.
In practical senario, however its better to use a single TCP packet with chained SMB headers triggering the bug with a single TCP packet as snort runs in pretty stateless mode and doesnt really checks weather the packet is a part of a valid TCP session.

In case anybody is interested:
Original advisory: http://www.iss.net/threats/257.html
PoC: http://eos-india.net/abhisek/codez/exploits/snort_dcerpc_pwn-v0.1.c

Users of vulnerable version of snort should try to upgrade to Snort 2.6.1.3 ASAP.

posted at: 17:45 | path: / | permanent link to this entry

Tue, 16 Jan 2007 18:24:00 IST

Ruby-Pcap patch

Ruby-pcap is a pretty neat ruby binding for the pcap library.

While working with ruby-pcap, I found the lack of support for pcap_findalldevs API in the binding..
so Here is a small patch to add it into the ruby-pcap extension libary.

Here is the test case.

posted at: 18:24 | path: / | permanent link to this entry

Sat, 06 Jan 2007 15:13:00 IST

IMPORTANCE OF SIGNED/UNSIGNED

Just came across after a very trivial change..

#include <stdio.h>

void crash()
{
   char buf[20];
   char *p = "\xff\xff\xff\xff\xff\xff";

   sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
                                          p[0],
                                          p[1],
                                          p[2],
                                          p[3],
                                          p[4],
                                          p[5]);

   printf("%s\n", buf);
}

int main()
{
   crash();

   return 0;
}
Compiled & Run
neo@sauron ~/documents/website/blog $ ./a.out
ffffffff:ffffffff:ffffffff:ffffffff:ffffffff:ffffffff
Segmentation fault
neo@sauron ~/documents/website/blog $ gdb ./a.out
GNU gdb 6.4
Copyright 2005 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".

(gdb) r
Starting program: /home/neo/documents/website/blog/a.out
Failed to read a valid object file image from memory.
ffffffff:ffffffff:ffffffff:ffffffff:ffffffff:ffffffff

Program received signal SIGSEGV, Segmentation fault.
0x66666666 in ?? ()
(gdb) i r $eip
eip            0x66666666       0x66666666
(gdb)
Evident stack overflow!
But isnt ff:ff:ff:ff:ff:ff is what I expected?

A little fix
neo@sauron ~/documents/website/blog $ diff ~/junk/crash.c ~/junk/crash2.c
6c6
<    char *p = "\xff\xff\xff\xff\xff\xff";
---
>    unsigned char *p = "\xff\xff\xff\xff\xff\xff";
neo@sauron ~/documents/website/blog $   
Compiled & Run
neo@sauron ~/documents/website/blog $ gcc ~/junk/crash2.c
neo@sauron ~/documents/website/blog $ ./a.out
ff:ff:ff:ff:ff:ff
neo@sauron ~/documents/website/blog $    

So how many apps are vulnerable like this?
and no, -fstack-protector probably wont fully protect you.. but ofcourse it will pretty much obscure the exploitation path, got to look into it.. apparently looked like a canary based protection..

GCC Stack protector adds following:

In procedure prolog:

0x0804842d :   mov    %gs:0x14,%eax
0x08048433 :  mov    %eax,0xfffffff0(%ebp) 
0x08048436 :  xor    %eax,%eax
In procedure epilog:
0x080484c0 : mov    0xfffffff0(%ebp),%eax
0x080484c3 : xor    %gs:0x14,%eax 
0x080484ca : je     0x80484d1  
0x080484cc : call   0x8048330 <__stack_chk_fail@plt> 

In procedure prolog, a 32 bit cookie is placed at (SFP - 8) which is checked with the original at %gs:0x14 which if not matched, __stack_chk_fail overflow handler is trigger thus abort()'ing. So apparently there is no way of corrupting saved EIP without corrupting this cookie and hence the protection.

Bypassable?

Idea: I have a process (in memory execution context of a program.. remember?) that contains a function `do_something()`, can I at runtime patch this function or replace this function with a completely new externally supplied code? Patch GOT? Patch PLT? ptrace will help? google for ELF internals?


Thank god, feeling better :-)

posted at: 15:13 | path: / | permanent link to this entry

Wed, 03 Jan 2007 18:17:00 IST

PAIN IN THE HEAP

Weirdly enough, a small apparently elegant looking code working fine on my box and when statically compiled on my box works fine on all others boxens I tested. But trouble striked when of my colleague svn co'd my code and tried writing some plugin. The blue sky turned grey for me as it began crashing in bootstrapping of the app itself, apparently in a linked list implementation of circular queue.

After considerable amount of fiddling with..

neo@sauron ~/ROOT/work/v2/production $ cat > gdb
break *(start_loader+116)
command 1
p entry
p entry->name
p entry->func
p entry->next
p entry->prev
continue
end

(gdb) source ./gdb
Breakpoint 1 at 0x80ca831: file ra_loader.c, line 128.
(gdb) r
.
.
Breakpoint 1, 0x080ca831 in start_loader () at ra_loader.c:128
128           if(strncmp(entry->name, "bootstrap", strlen("bootstrap")) == 0)
{
$141 = (struct load_entry_t *) 0x828d8f0
$142 = 0x4fe1 
$143 = (void (*)()) 0x4fe1 $144 = (struct load_entry_t *) 0xb7ee552c $145 = (struct load_entry_t *) 0x0 Program received signal SIGSEGV, Segmentation fault. 0x080ca831 in start_loader () at ra_loader.c:128 128 if(strncmp(entry->name, "bootstrap", strlen("bootstrap")) == 0) {

Initially looked like heap overflow somewhere which resulted in pointer overwrites, but after considerable effort, found its the same common flaw in pointer link/unlink of list blocks.

Lesson learned: try not to write up a quick queue/list implementation playing with malloc'd ptrs, prefer using well tested ones.. probably `man queue` (sys/queue.h) and rtfm helps..

http://www.gnu.org/software/libc/manual/html_node/Tracing-malloc.html#Tracing-malloc

posted at: 18:17 | path: / | permanent link to this entry

Tue, 19 Dec 2006 18:08:00 IST

NEW BLOG - Post HDD crash session

Finally recovered/configured my pyblosxom again.. after a long fight since I forgot most of the configuration and manual patches that I applied to my previous pyblosxom installation..

and btw.. since 2006 is almost over and I am pretty convinced that I have perfectly wasted this entire year..so, time to buckle up with renewed enthusiasm and stop being an idiot and actually write some code and feel better..

to start with..
Today's fortune: The great pleasure in life is doing what people say you cannot do

posted at: 18:08 | path: / | permanent link to this entry

Mon, 27 Nov 2006 15:58:00 IST

FOSS.IN '06 After Effects..

Back home after my first bangalore && FOSS.IN trip.. although the flight got delayed by 2 hours or so due to heavy fog at bangalore airport but I returned home safely near about 11:30am on 26th Nov (Sunday).. yeah missed the last day and also ``Coffee @ Y!``.



The entrance to the J.N Tata auditorium was pretty neat but somehow I couldnt figure out the FOSS.IN banner in the front in the first go and I have to go and confirm with some random dude out there that it is indeed FOSS.IN :)
Anyways...



FOSS.IN '06 kicked off by an introductory speech by Atul Chitnis followed by lightening of FOSS lamp by various FOSS people from different states and then the keynote, by an Indian, for the first time in the history of FOSS.IN, Suparna Bhattacharya.

So overall it was a pretty nice trip.. finally meet up t3min4t0r and was also looking around for KingDiamond for some "Ruby moments" but couldnt find him.. :(


Although neither I know PHP nor I have any interest in it but still I attended Rasmus Lerdorf's talk on "Getting Rich with PHP5".. well mainly because I was about to attend "Porting Ruby to Symbian" talk but because of some gah..gah.. expression and words from Gopal turned me down :P, I moved to this PHP talk and finally when I was going home, I decided personally I think this was the best talk of "FOSS.IN 06" that I have attended..


Apart from that, Christoph Hellwig's talk on "Contributing to the Linux Kernel for Fun and Profit" and Suparna Bhattacharya's update on "EXT4 Development" was also pretty neat to me, mainly because I am a ``wannabe`` into the kernel world..

and finally, if you are interested in some pictures that I took, Click Here

posted at: 15:58 | path: / | permanent link to this entry

Fri, 17 Nov 2006 14:55:00 IST

SSL is secure, but are we?

Everytime I enter my credit card information or important user/pass information on web I always look for https with a certificate from some trusted authority, one of the best practices I learned while working with _sekuwity_ people.

But seems like security research has reached such a stage that software/automated security implementations are not enough to stay secure, users must be security concious for close to good online security.
Most of the people I came across never really care about those irritating SSL certificate warnings and just blindly click "OK" to go to their desiring page, least they know someone might actually be redirecting traffic which is fairly easy in a packet switched network and considering available tools like Ettercap, I think its pretty easy..

Now consider this situation, somebody redirecting your traffic to their box (at L2) instead of the original gateway by manipulating the ARP cache of your OS (ARP Poisoning) and ``The Man in the middle`` (between you and the gateway) has a ruleset on his firewall like:

iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j REDIRECT --to-port 31337
So? all your https traffic will be redirected to his proxy on port 31337... then? you might establish an SSL session with the ``Man in The Middle`` rather than the real server.. so? possibilities are endless.

Solution: Paranoia..

My ARP table is static..you cant poison me.. ok.. I will poison the person to whom you are connected :)

Now I have an idea, idea to implement a state based ARP inside the linux kernel. Basically idea is to make linux kernel stateful while processing ARP reponse packets. By default the kernel should be in non-accepting state for ARP response packets.. only when the kernel xmits an ARP packet to satisfy higher level networking requirements, it should go to accepting state for ARP response packet for a given IP-MAC(x) resolution and there should be timeout for switching back the kernel to non-accepting state if no packet arrives.

But again, this is just a very vague thought.. I really need get into the nitty-gritty details of the kernel network stack and the data structures and especially in the kernel land, its very easy to get lost and considering the stuff I am working on professionally these days, I dont think I will be able to do this in very near future..

posted at: 14:55 | path: / | permanent link to this entry

Comming to FOSS.in 06

So finally got leave, plane tickets for bangalore..to attend Foss.in

Supposed to land on bangalore on 23rd Nov '06 @ 11:30am or so.. but cant be that sure since its Air Deccan (the best affordable i could get at this time). Going to stay with my old time pal Hirosh in a place called ``Lakkasada`` or something similar.

Hope to meet lots of people I talk to everyday on IRC (you know who you are) :)

posted at: 14:30 | path: / | permanent link to this entry

Sat, 30 Sep 2006 11:05:00 IST

Durga Puja '06

Surely it is the biggest festival for bengalies.

This year I got the oppurtunity to try my hands on a Sony DSC-H2, so went for some hunting on Panchami along with my friends..

dsc00248 dsc00247 dsc00246 dsc00245 dsc00244 DSC00155 DSC00154 DSC00153 DSC00151 DSC00150 DSC00148 DSC00146 DSC00143 DSC00142 DSC00141 DSC00139 DSC00137 DSC00136 DSC00135 DSC00134

Time to go back boozing, in the mean time.. Click Here if you care to see some more Durga Puja 06 pics.

posted at: 11:05 | path: / | permanent link to this entry

Mon, 25 Sep 2006 18:30:00 IST

Therez more in life than ./

Just managed to wake myself up after around 4 hours sleep, post Sankarpur(06) trip which ended today.

Normally I prefer mountains (gosh! am a trekking lover) over sea, but this sea side trip was pretty good especially with the awesome food and considerably fine alchohol.

Time to upgrade my flickr account and upload some pictures..

posted at: 18:30 | path: / | permanent link to this entry

Sun, 17 Sep 2006 20:17:00 IST

RIP lilo

May his soul rest in peace!!

posted at: 20:17 | path: / | permanent link to this entry

Fri, 15 Sep 2006 16:28:00 IST

RUBY ROCKZ!!

Oh yes, I am getting more and more impressed with Ruby.

Ruby being an apparently *very* simple and aesthetically pleasing language, but internally it is very complex in its implementation along with quite a few awesome and very intelligent hacks.

People interested in giving ruby a shot should surely start with the following:
* About Ruby
* Ruby in 20 min

People interested in Ruby internals can take a look at "Ruby Hacking Guide".

Oh and before saying bye for the day, I would love to give away some fun.
A nice and *probably* usable ruby shell ;-)

#!/usr/bin/ruby
require 'readline'

class RShell

   def initialize()
      Signal.trap('INT') {
         puts "Enter exit/quit to exit shell"
      }
   end

   def unixcmd?(cmd = nil)
      return nil unless cmd

      paths = ENV["PATH"].split(':')
      paths.each do |p|
         file = "#{p}/#{cmd.split(' ',2)[0]}"
         return true if File.exists? file
      end

      false
   end

   def run

      loop do
         cmd = Readline::readline("rsh #{ENV['PWD']}> $ ", true)
         exit if cmd =~ /exit|quit/
         if unixcmd? cmd
            system(cmd)
         else
            begin
               eval cmd
            rescue
               puts "Command not found"
            end
         end
         
      end
      
   end

end

RShell.new.run

http://eos-india.net/abhisek/codez/misc/rsh.rb

posted at: 16:28 | path: / | permanent link to this entry

Mon, 04 Sep 2006 22:58:00 IST

RIGHT or WRONG ??

Recently I came across a class of people who are firm believers of relativity and the concept of reference frame. According to them there doesnt exists anything which is absolutely right or absolutely wrong. This discussion about right or wrong was going on over a dinner table along with drinks and most of us including the speaker was considerably drunk. So at that time I couldnt really find any vulnerability in this statement.

But later, with possibly better realization, I think we are living in a world where there are certainly _very_ few people who truely grasp the concept of relativity and that of reference frame, ofcourse me being in the majority.
Not that the word relativity here has anything to do with "The Theory of Relativity" technically, but conceptually or psychologically it might have some relation which I couldnt figure out yet. So its better to consider _generally_ right as right and _generally_ wrong as wrong in most circumstances especially where it has something to do with the interest of the _general_ else it might turn up into cheap hypocricy to hide weakness/cheapness.

Although somewhat irrelevant, but I always used to think that I am a supporter of modern education/thinking but somehow now I think I am quite back dated from the point of view of mentality, because I am really sick and tired of artificial people trying to follow Dale Carnegie blindly.

posted at: 22:58 | path: / | permanent link to this entry

Sun, 03 Sep 2006 11:24:00 IST

Ruby Libnids Binding

Libnids is an implementation of an E-component of Network Intrusion Detection System. It emulates the IP stack of Linux 2.0.x. Libnids offers IP defragmentation, TCP stream assembly and TCP port scan detection.

Libnids Homepage: http://libnids.sf.net

For the uninitiated, each TCP session is identified by calculating a hash on
i) Source IP address
ii) Source Port
iii) Destination IP address
iv) Destination Port

So for an user space TCP stream reassembly, a hash table needs to be maintained and on capture of every TCP packet, the hash is to be calculated and the packed should be classified into an appropriate stream.

Libnids mimics Linux 2.0.x TCP stack implementation on user space.

Such wonderful power of monitoring and uniquely identifying each TCP session if available in Ruby would make it more powerful, with this idea in mind I did the Ruby wrapper for libnids library last week.

The project page is located at: http://ruby-libnids.rubyforge.org
I upload testing codes at: http://ruby-libnids.rubyforge.org/testing/

An example script may look like this.

require 'libnids' 

$l = 0 

def callback(opts = nil, ss = nil) 
   return unless opts 

   case opts["nids_state"] 
      when NIDS::STATE_JUST_EST 
         str = String.new
         str += "[NEW CONNECTION] #{opts['saddress']}:#{opts['sport']} --> "
         str += "#{opts[ 'daddress']}:#{opts['dport']}" 

      when NIDS::STATE_DATA 
         str = String.new
         str += "[DATA] #{opts['saddress']}:#{opts['sport']} --> "
         str += "#{opts['daddress' ]}:#{opts['dport']} " 
         str += "[SEND: #{opts['server_data_len']}] [RECV:
#{opts['client_data_len']}]" 

         puts str

      when NIDS::STATE_CLOSE, NIDS::STATE_RESET 
         str = String.new
         str += "[CLOSE] #{opts['saddress']}:#{opts['sport']} --> "
         str += "#{opts['daddress ']}:#{opts['dport']}" 

   end 
end
$l = NIDS::Sniffer.new 
$l.register_tcp(self, :callback) 
$l.run 

This thing is pretty new at the moment and tested only on a network of around 10 systems. I dont think it will be much efficient on high speed networks with large number of parallel TCP connections.

and oh, last but not the least, special thanks to Sumit Datta for making the webpage for http://ruby-libnids.rubyforge.org

posted at: 11:24 | path: / | permanent link to this entry

PyBlosxom works!!!

Finally seems like my blog is not junking up Planet India and I hope sankarshan and G0SUB wont be mad at me anymore regarding this, although its a seperate issue that they have many more things to be mad at me.

As usual the credit undoubtably goes to t3rmin4t0r for pointing me out the actual problem and also providing an appropriate fix.

The two things which I used for the fix are:
(a) t3min4t0r's hacked copy of pyfilemtime.py plugin for pyblosxom
(b) added lacking "<pubDate>$date $ti:00 $timezone</pubDate>" in my story.rss pointed out by t3min4t0r

posted at: 10:55 | path: / | permanent link to this entry

Wed, 12 Jul 2006 23:31:00 IST

LINUX SYS_PRCTL BUG/BACKDOOR/FEATURE FUN

From man prctl(2):
prctl() is called with a first argument describing what to do (with values defined in <linux/prctl.h>),
and further parameters with a significance depending on the first one.

There is a bug/feature in sys_prctl() in kernel/sys.c exploiting which a process can be forced to dump
its core in directories which should not be writable by the process.

Original Advisory: http://rhn.redhat.com/errata/RHSA-2006-0574.html

This vulnerability is fixed in the following patch:
http://www.kernel.org/diff/diffview.cgi?file=%2Fpub%2Flinux%2Fkernel%2Fv2.6%2Fincr%2Fpatch-2.6.17.3-4.bz2;z=2

My following hotfix should prevent exploitation of the above mentioned vulnerability from publicly used techniques.

Hotfix: http://www.freeshell.in/~abhisek/linux_prctl_lkm.tar.gz

Some dmesg output while playing around with this hotfix.

neo@compaq blog $ dmesg | tail -n 11
Loading sys_prctl hotifx
sys_call_table: 0xc0453780
Unloading sys_prctl hotfix
Loading sys_prctl hotifx
sys_call_table: 0xc0453780
Denied possible exploitation attempt [uid=1000 gid=100 pid=13805]
Unloading sys_prctl hotfix
Loading sys_prctl hotifx
sys_call_table: 0xc0453780
Denied possible exploitation attempt [uid=1000 gid=100 pid=14008]
Unloading sys_prctl hotfix
neo@compaq blog $

Alright, another nice linux kernel bug got fixed. Kudoz to the RedHat Security Team guys for finding such subtle bug/feature in the heart of the linux kernel.

Now initially a lot of people had doubt weather this bug is actually exploitable even after Paul Starzetz confirmed (made fun) of the bug and its ease of exploitation.

Since I am documenting it for some unknown reason, I should mention clearly for the poor people out there, THIS BUG _IS_ EXPLOITABLE FOR LOCAL PRIVILEGE ESCALATION and rm -rf /& is quite possible in this case.

For those who believe in ``seeing is believing'' can take a look at: http://www.freeshell.in/~abhisek/rs_prctl_kernel.c and dotslah their way to some fun.

References:
http://www.kernel.org/diff/diffview.cgi?file=%2Fpub%2Flinux%2Fkernel%2Fv2.6%2Fincr%2Fpatch-2.6.17.3-4.bz2;z=2 http://www.securityfocus.com/bid/18874

posted at: 23:31 | path: / | permanent link to this entry

Wed, 14 Jun 2006 20:38:00 IST

_THE_ SOFTWARE DEVELOPMENT LIFE CYCLE

Software doesn't just appear on the shelves by magic. That program shrink-wrapped inside the box along with the indecipherable manual and 12-paragraph disclaimer notice actually came to you by way of an elaborate path, through the most rigid quality control on the planet. Here, shared for the first time with the general public, are the inside details of the program development cycle.

   
1. Programmer produces code he believes is bug-free.
2. Product is tested. 20 bugs are found.
3. Programmer fixes 10 of the bugs and explains to the testing department that the other 10 aren't really bugs.
4. Testing department finds that five of the fixes didn't work and discovers 15 new bugs.
5. See 3.
6. See 4.
7. See 5.
8. See 6.
9. See 7.
10. See 8.
11. Due to marketing pressure and an extremely pre-mature product announcement based on overly-optimistic programming schedule, the product is released.
12. Users find 137 new bugs.
13. Original programmer, having cashed his royalty check, is nowhere to be found.
14. Newly-assembled programming team fixes almost all of the 137 bugs, but introduce 456 new ones.
15. Original programmer sends underpaid testing department a postcard from Fiji. Entire testing department quits.
16. Company is bought in a hostile takeover by competitor using profits from their latest release, which had 783 bugs.
17. New CEO is brought in by board of directors. He hires programmer to redo program from scratch.
18. Programmer produces code he believes is bug-free....

THE GRAPHICAL REPRESENTATION



Original Source:
http://www.urbaczewski.com/humor/softdevcycle.htm
http://murali.weblogs.us/images/software_development1.jpg

posted at: 20:38 | path: / | permanent link to this entry

Wed, 31 May 2006 19:06:00 IST

GAMES WITH LINUX MEMORY PERMISSIONS

Today while testing my shellcode, I suddenly had a weird idea. I used to think the mainline 2.6 branch of linux kernels from kernel.org is pretty secure these days and application level exploitation over these latest linux kernels are extinct concept because of the secure by default memory permissions.

Well, lets get going in my attempt to dig deeper into linux memory management and paging implementations.
Currently I am running Gentoo with 2.6.14 on my laptop. The memory mappings as available from /proc looks something like this:
note: I am using the gentoo-sources kernel from portage without any hack or external patches like GrSecurity/PaX or SELinux/ExecShield.

neo@compaq ~ $ cat /proc/self/maps
08048000-0804c000 r-xp 00000000 03:06 38646      /bin/cat
0804c000-0804d000 rw-p 00003000 03:06 38646      /bin/cat
0804d000-0806e000 rw-p 0804d000 00:00 0          [heap]
b7eb8000-b7fc1000 r-xp 00000000 03:06 87733      /lib/libc-2.3.5.so
b7fc1000-b7fc2000 ---p 00109000 03:06 87733      /lib/libc-2.3.5.so
b7fc2000-b7fc3000 r--p 00109000 03:06 87733      /lib/libc-2.3.5.so
b7fc3000-b7fc6000 rw-p 0010a000 03:06 87733      /lib/libc-2.3.5.so
b7fc6000-b7fc9000 rw-p b7fc6000 00:00 0
b7fe7000-b7ffc000 r-xp 00000000 03:06 87744      /lib/ld-2.3.5.so
b7ffc000-b7ffd000 r--p 00014000 03:06 87744      /lib/ld-2.3.5.so
b7ffd000-b7ffe000 rw-p 00015000 03:06 87744      /lib/ld-2.3.5.so
bf8e7000-bf8fc000 rw-p bf8e7000 00:00 0          [stack]
ffffe000-fffff000 ---p 00000000 00:00 0          [vdso]
neo@compaq ~ $

Looking at the memory mappings, its quite apparent that there doesnt exists any segment with both write ("w") _AND_ execute ("x") permission. I have been looking into such memory mappings for quite some time now, assuring my paranoid mind that I am quite secure, atleast from arbitrary code injection/execution level exploitation techniques.

Due to some reason and unable to find out the technical reasonings for some unexpected behaviour, I started playing with it.
The following code can be used to test the default memory permissions implemented by my kernel.

#include <stdio.h>
/*
BITS 32

GLOBAL _start

_start:

   call getString
   db "Hello World",0x0a,0x00

getString:
   pop ecx
   mov edx, 12
   mov ebx, 1
   mov eax, 4
   int 0x80

   xor eax,eax
   xor ebx, ebx
   inc eax
   int 0x80
*/
static char code[] =
"\xe8\x0d\x00\x00\x00\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64"
"\x0a\x00\x59\xba\x0c\x00\x00\x00\xbb\x01\x00\x00\x00\xb8\x04\x00"
"\x00\x00\xcd\x80\x31\xc0\x31\xdb\x40\xcd\x80";

int main(int argc, char **argv)
{
  int (*funct)();
  char temp;

  funct = (int (*)()) code;

  printf("code is at 0x%x\n",&code);
  printf("sizeof code is 0x%x bytes\n",sizeof(code));

  printf("Checking read/write on code's segment\n");
  temp = code[10];   /* Read works */
  code[10] = 0xff;   /* Write works */
  code[10] = temp;   /* Restore the byte */
  printf("All works\n");

  printf("Executing code\n\n");
  (int)(*funct)();
}

To my surprise (yeah may be I was wrong) I have results like this.

neo@compaq ~/CVSROOT/ $ gcc helloworld.c
neo@compaq ~/CVSROOT/ $ ./a.out
code is at 0x80496c0
sizeof code is 0x2c bytes
Checking read/write on code's segment
All works
Executing code

Hello World
neo@compaq ~/CVSROOT/ $

Yes code was actually rwx (Readable,Writable, Executable).
Looking into address of ``code'' (0x080496c0), it appears to be in the .data segment which is supposed to be non-executable as per /proc/{pid}/maps.

0x080496a0->0x080496ec at 0x000006a0: .data ALLOC LOAD DATA HAS_CONTENTS

So whats the meaning of this?
a) /proc/self/maps gives incorrect results?
b) I am doing something wrong?
c) Explanation is already available, just that I need to look for it?

I'll dig more into it and post some results if I find out something. In the mean time if somebody accidentaly lands up in this thing and have something to say, please drop me a mail at abhisek[dot]datta[at]gmail[dot]com

And oh, if anybody is interested in testing the kernel's memory permissions/protections then I'll suggest take a look at:

http://www.adamantix.org/paxtest/

Some links for Linux kernel security stuff

http://www.grsecurity.net 
http://pax.grsecurity.net 
http://www.nsa.gov/selinux/index.cfm
http://www.redhat.com/f/pdf/rhel/WHP0006US_Execshield.pdf

posted at: 19:06 | path: / | permanent link to this entry

Thu, 25 May 2006 00:00:00 IST

BUBBLE BUBBLE

Once upon a time, not so long ago but quite some time ago, when I was doing my first year graduation, somebody asked me something about bubble sort (yes probably the most simple sorting algorithm) and I remember I could not answer. Well, now here is my little try at the question posed to me quite some time ago...



;;
;; BUBBLE SORT IN 32BIT x86 ASSEMBLY
;; SHOULD WORK OVER LINUX KERNEL

;; THIS MADNESS IS DEDICATED TO THE GRAND OCCASSION OF 2nd JUNE 2006
;; HAIL PEPSI
;; MAY YOU AND I REST IN PEACE SOMEDAY
;;
;; POSITION INDEPENDENT ASSEMBLY COMPONENT
;; YOU CAN MAKE A RELIABLE SHELLCODE OUT OF THIS
;; EVIL HAXORZ CAN USE PWNED BOX FOR DOING BUBBLE SORT
;;
BITS 32

GLOBAL _start

%define FD_STDOUT    1
%define FD_STDIN     0

%define __NR_READ    3
%define __NR_WRITE   4
%define __NR_EXIT    1

_start:
   push ebp
   mov ebp, esp

   sub esp, 4

   call helloStr
   db "Enter the number of elements to sort: ",0x00
   
helloStr:      
   pop ecx
   push ecx
   call sub_PrintStr

   call sub_ReadDword
   mov ecx, eax
   mov dword [ebp - 4], ecx

elementReaderLoop:

   call getAskString
   db "Enter number: ",0x00
   
getAskString:
   pop esi
   push ecx
   
   push esi
   call sub_PrintStr
   pop esi
   pop ecx

   push ecx
   call sub_ReadDword
   pop ecx
   
   push eax

   loop elementReaderLoop

   mov eax, dword [ebp - 4]
   push eax             ; Number of elements to sort
   int3
   call sub_BUBBLES

   int3
   call sub_Exit

   ; sub_BUBBLES(n, A[n])
   ; This procedure will sort A[n] in descending order using the bubble sort algorithm
   ; The _list_ A is modified _in_ _place_ for sorting
sub_BUBBLES:
   push ebp,
   mov ebp, esp

   call startMsg
   db "Bubble sort start..",0x0a,0x00
startMsg:
   pop ecx
   push ecx
   call sub_PrintStr

   mov ebx, [ebp+8]
   dec ebx
   xor ecx, ecx

   add ebp, 12 ; EBP now points to param array base
   
bubbleSortLoop1:
   
   mov edx, ecx
   
bubbleSortLoop2:
   pusha
   mov eax, [ebp + edx * 4]
   mov ebx, [ebp + ecx * 4]
   cmp eax, ebx
   popa
   jl swap
   jmp loop2

swap:
   push dword [ebp + edx * 4]
   push dword [ebp + ecx * 4]
   pop dword [ebp + edx * 4]
   pop dword [ebp + ecx * 4]

loop2:
   inc edx
   cmp edx, ebx
   jl bubbleSortLoop2

   inc ecx
   cmp ecx, ebx
   jl bubbleSortLoop1

   call endMsg
   db "Bubble sort ends..",0x0a,0x00
endMsg:
   pop ecx
   push ecx
   call sub_PrintStr
      
   sub ebp, 12   ; Restore EBP
      
   mov esp, ebp
   pop ebp
   ret

   ; sub_Strlen(str_ptr)
sub_Strlen:
   push ebp
   mov ebp, esp

   mov edi, [ebp+8]
   xor ecx, ecx
   xor al, al
   not ecx
   cld
   repne scasb
   not ecx
   dec ecx 
   
   mov eax, ecx
   
   mov esp, ebp
   pop ebp
   ret
   
   ; sub_PrintStr(str_ptr)
sub_PrintStr:
   push ebp
   mov ebp, esp

   mov eax, [ebp+8]
   push eax
   call sub_Strlen

   mov ebx, FD_STDOUT
   mov ecx, [ebp+8]
   mov edx, eax
   mov eax, __NR_WRITE
   int 0x80

   mov esp, ebp
   pop ebp
   ret

   ; sub_PrintRaw(data_ptr, size)
sub_PrintRaw:
   push ebp,
   mov ebp, esp

   mov ebx, FD_STDOUT
   mov ecx, [ebp+8]
   mov edx, [ebp+12]
   mov eax, __NR_WRITE
   int 0x80

   mov esp, ebp
   pop ebp
   ret

   ; sub_ReadDword() 
sub_ReadDword:
   push ebp
   mov ebp, esp

   sub esp, 16
   
   mov ebx, FD_STDIN
   lea ecx, [ebp - 16]
   mov edx, 16
   mov eax, __NR_READ
   int 0x80
   
   xor ecx, ecx
   lea esi, [ebp - 16]
   
endFinderLoop:
   cmp byte [esi + ecx], 0x0a
   je endFinderLoopEnd
   inc ecx
   jmp endFinderLoop

endFinderLoopEnd:
   mov byte [esi + ecx], 0x00

   dec ecx

   xor eax, eax
   xor edx, edx
atoiLoop:
   xor ebx, ebx
   add bl, byte [esi + edx]
   sub bl, 0x30

   push edx

   push 10
   mul dword [esp]
   add eax, ebx

   add esp, 4

   pop edx
   
   cmp edx, ecx
   je atoiLoopOut
   
   inc edx
   jmp atoiLoop

atoiLoopOut:
  
   mov esp, ebp
   pop ebp
   ret

sub_Exit:
   mov eax, __NR_EXIT
   xor ebx, ebx
   int 0x80

Thank You and bye bye World for today

posted at: 00:00 | path: / | permanent link to this entry

Made with PyBlosxom