My muttrc

Ankur asked me to put out a blog post describing my mutt setup since I had been using mutt for a while now. Most of my muttrc is borrowed from various resources on the internet, so what I’ll do here is dump my muttrc so that anyone interested can try out snippets and options they haven’t seen before. It has a couple of unique quirks like ldap lookups and adding zimbra invites from emails. I haven’t written those either; I got them from a couple of colleagues at work.

So here goes:

set abort_nosubject=ask-yes
set abort_unmodified=ask-yes
set copy=yes
set delete=yes
#set forward_edit=yes
set include=yes

set timeout=10 set mail_check=5 set sort=threads set sort_aux=date set sort_re set mark_old=no unset wait_key

###########################

Account stuff

########################### set spoolfile=imaps://mail.domain.com/Inbox set folder=imaps://mail.domain.com/ set imap_user=siddhesh@domain.com set imap_pass=super_secret_password set imap_check_subscribed=yes

set record=imaps://mail.domain.com/Sent set postponed=imaps://mail.domain.com/Drafts

set header_cache=/home/siddhesh/Mail/

set smtp_url=smtp://smtp.domain.com/ set from=“siddhesh@domain.com” set realname=“Siddhesh Poyarekar”

set mime_forward=yes set mime_forward_rest=yes

##########################

Address Book

##########################

source ~/.mutt-alias set alias_file=~/.mutt-alias set query_command = “/home/siddhesh/.bin/mutt-ldap.py ‘%s’”

#############################################################

Contents of mutt-ldap.py

############################################################# ##!/usr/bin/env python # #import ldap, sys #myname = sys.argv[0] # #try: #    search = sys.argv[1] #except: #    print ‘Usage: %s <name> [<name> …]’ % myname #    sys.exit(1) # #search = sys.argv #users  = [] #l      = ldap.initialize(‘ldap://ldap.domain.com:389’) # #for s in search: #    if s == myname: #        continue # #    x = l.search_s(‘ou=Users,dc=domain,dc=com’,ldap.SCOPE_SUBTREE,‘(|(cn=’ + s + ‘)(sn=’ + s + ‘)(uid=’ + s + ‘))‘,[‘cn’,‘uid’,‘sn’,‘mail’]) #    for user in x: #        try: #            uid  = user[1][‘uid’][0] #            mail = user[1][‘mail’][0] #            cn   = user[1][‘cn’][0] #        except: #            continue #        users.append(’<%s>\t%s’ % (mail, cn)) # #total = len(users) #print ‘LDAP query: found %d’ % total #if total == 0: #    sys.exit(1) # #for i in users: #    print i ##############################################################

##############################

Run imapfilter on F5

############################## macro generic <f5> “<shell-escape> imapfilter<Enter>$” “Filter messages using imapfilter” macro index <f5> “<shell-escape> imapfilter<Enter>$” “Filter messages using imapfilter” macro pager <f5> “<shell-escape> imapfilter<Enter>$” “Filter messages using imapfilter”

macro index <f3> “T~N<Enter>;N;t$” “Mark all as Read”

##############################

The look

############################## #

Pretty Colors

color status black yellow # The status line is barely visible to my eyes otherwise :( color index brightgreen default ~N color index green default ~O color index red default ~D  # deleted color index brightmagenta default ~T  # tagged color index brightyellow default ~F  # flagged color header green default “^Subject:” color header yellow default “^Date:” color header yellow default “^To:” color header yellow default “^Cc:” color header yellow default “^Bcc:” color header yellow default “^From:” color header red default “^X-.*:”

set index_format=“%Z %{%d-%b-%Y %X} %-15.15L (%?l?%4l&%4c?) %s” set folder_format=“%N %F %2l %-8.8u %-8.8g %8s %d %f”

auto_view text/html

set markers=no set smart_wrap=yes set wrap=80

#############################

zimbra invites

############################# macro pager Z ‘<view-attachments><search>text/calendar<enter><pipe-entry>curl -k -u siddhesh –data-binary @- https://domain.com/calendar?fmt=ics<enter>q'


FUDCon Notes on my Security Exploits Session

I was asked  by a couple of people for notes on the security exploits session that I conducted at FUDCon. I had posted the code samples on the talk page, but that is probably a little terse, so here’s a little write-up to support the code samples. To repeat what I had said multiple times earlier; I am not a security researcher, not even a security freak. This topic was suggested to me by Amit Shah, and I developed an interest in it due to my original interest, which is operating systems tools. The preparation of this talk got me interested in security, but only through the perspective of operating systems tools and programs, so I am still relatively indifferent to the subject of web-based security.

I started preparing for the session fairly late; i.e. 2 days before FUDCon. I am a little familiar with glibc code and with the way the compiler, linker, loader, etc. work on Linux, so that helped me understand a lot of the concepts behind exploits fairly easily. But concepts != working code and getting exploit code to work was the real challenge, especially when I had just about 3 evenings+nights for it. I had started with an idea of showing stack smashing and privilege escalation examples, but given the time constraint, audience level (college students) and also the constraint of my knowledge, I decided to restrict it to stack based attacks. All of the examples have a buffer which is being written to without checking for bounds of that buffer, typically with an strcpy.

The shellcode sample:

The shellcode sample as well as the final vulnerability demo (smash.c and vulnerable.c) were derived from the article Stack Smashing for Fun and Profit. That is a great article that explains in much more detail than I went into in my session, as to how the shellcode exploit can be developed.The core idea of this is:

  • Obtain the binary equivalent of execve (name[0], name, NULL ) where name = {“/bin/sh”, NULL}
  • Append additional data to the binary data and pass it to the buffer copy routine (strcpy) in such a way that, it writes the location of the first instruction in the above binary equivalent into the location of the return address
The exploit is fairly straightforward, except that the instructions no longer work as is on Linux. These instructions require that the process image is set up in a manner that the page mapped to implement the program stack should have execute permissions. By default on recent Linux distributions (I tried this on F-15, but I am certain this should be true for at least F-13, if not earlier), the linker writes out binaries in a manner that the stack, when set up for a process, only has read and write permissions.

I spent a lot of time trying to figure out where this was set and finally found the -z option of the linker. So to write out a binary that sets up an executable stack, I had to call the linker with -z execstack. This finally enabled me to get the shellcode working.

The actual exploit

Once the shellcode was done, I could get the final vulnerability working and I immediately set about trying it. The exploit is based on the above shellcode example, except for one difference. The shellcode example is just that, an example. It is not an actual exploit; it is just a roundabout way to get a shell. The exploit I was about to do was a real crack. The idea now is to accept a string as input, which is then fed in to make a regular and buggy program provide you with a shell.

To imagine how this would work, think of the program that gives you a login prompt. In the context of this exploit, you should be able to input a crafted string into this login prompt and have it give you a shell without actually knowing the password! This is what the actual exploit ought to look like.

Again, writing the exploit was the easy part; getting it to run was quite another thing altogether. The exploit works as follows:

  • Pages of memory are generally mapped at the same addresses for processes, so the top of stack for a process can be a good starting estimate for the top of stack for another process. From that point on, you need a finite number of guesses to get to the point in stack where the instructions have been injected
  • The smash program records its own top of stack and prepares a string such that it the return address will be overwritten by the top of stack address. The string obviously begins with shell code. To improve the chances of hitting valid instructions in the code, the buffer is written over by a lot of single-byte NOP instructions just before the shellcode instructions
  • The smash program executes a shell with an environment variable exported ($EGG). This environment variable can now be used to execute the vulnerable program within that shell. This could have been done differently too, like storing the output to a file and executing the vulnerable program with input from that file. So the way input is given doesn’t really matter here
In all of this, there is one assumption that caused the program sample to not work; the assumption that memory maps are at predictable addresses. Recent kernels (quite some time ago actually) have a new security mechanism called Address Space Randomization which ensures that memory pages are loaded at random offsets. This meant that our educated guess would no longer work. So to be able to actually do this demo, I would have to disable address space randomization. I do that with:

echo 0 > /proc/sys/kernel/randomize_va_space

Even with this, my example would not execute by itself and would end with a SIGILL. I suspect this has something to do with the fact that my systm is x86_64 while the samples are all 32-bit. Our overflow string does not seem to agree with the instruction set on my system. In any case, it seems to run just fine inside a debugger. So if you run smash to get a shell, run gdb vulnerable and then run it with $EGG, you get the shell! At least I had a demo now.

Jump to libc

While I was trying out the shellcode example, I continued thinking about various other ways in which I could get a shell. One of the methods I thought of was to overwrite the return address with the address of the system() glibc call and pass the string via stack. I later found out via Huzaifa that this is in fact a documented way to exploit unchecked buffers on stack. Huzaifa also said that I may be missing out on something there and gave me some tips on finding the right resources for this. I still could not get this working, but at least I found out why the exploit did not work.

This exploit seemed attractive to me because it does not require an executable stack. The instructions I want to execute are already there in memory. So I only have to overwrite the return address and continue writing “/bin/sh” on the stack. I first tried with x86_64 in this case, because I was going by my own idea at that time. I soon figured out that the system() function on x86_64 did not take function arguments from stack. It took the argument from the %rdi register. My devious plan had been foiled! I did not give up however and looked at the system() implementation on i686. This retained the old behaviour of popping arguments from the stack, so my exploit was still possible here.

Not. My code was correct, but every time I run the program, the address of system() had just 3 bytes set. So it would always look something like: 0x00aabbcc. This was bad news because this meant that I cannot continue writing the shell string into the stack (strcpy stops copying when it encounters a 0x0). This means that I can call system() (like I was able to on x86_64 too), but I cannot pass it an argument. After trying enough number of times, I concluded that this must be a security feature. This was backed up by the tip Huzaifa had shared with me to (ironically) get the exploit to work. This was perhaps the first documentation of a return to libc exploit by Solar Designer. In his explanation, Solar designer mentioned that a way to fix this would be to ensure a 0x00 in the address, which is precisely what is happening here.

This obviously does not deny the fact that such an exploit can be carried out if you want to call functions that do not have arguments. Think for example, of a function that executes a shell ;)

Conclusion

The last modify example was a simple little trick I wrote on the last day to demonstrate how buffer overflows work and how they can be used to alter program flow. That again is not an exploit at all. At most, it can be called… a buffer overflow ;)

I had even more fun preparing for this session than actually presenting it because it taught me a lot more than I could ever have done by just reading literature. I hope those who attended my session at FUDCon enjoyed the session too.


FUDCon Pune 2011 Day 3: Hack and eat

The last day of FUDCon. I had not slept much the last couple of nights, so I slept in a little late. Due to this I reached the venue late too and found that a lot of the speakers had reached late and that seemed to have got the volunteers (understandably) a little annoyed. All of the action was to happen just in the auditorium and the seminar halls this time and I stuck mostly to the auditorium for most of the day. I had planned to work on the libgqpid library, but I had not decided what it is that I was going to do. I started off by writing my day 1 post. That was quickly followed by lunch, where we hogged on pizzas.

I told Kushal by that time that I will work on autotoolizing libgqpid since he was busy working on his book. I started working on that after lunch, quickly finding out that there are a few things that wouldn’t work very easily there.

libgqpid is a wrapper around the apache c++ client library and the library check for the qpid client library would have to be in c++. autotools does not have any macros for c++ library checks, so I had to write a check that looked like this:

AC_LANG_PUSH([C++])

AC_MSG_CHECKING([if qpid c++ client libraries are present]) AC_LINK_IFELSE( [AC_LANG_PROGRAM([#include <qpid/messaging/Connection.h>], [qpid::messaging::Connection con])], [QPID_LIBS=“$LIBS”], [AC_MSG_ERROR([qpid c++ client development libraries not found])])

AC_LANG_POP

After this one little hurdle it was pretty much smooth sailing and the result was a pull request to Kushal for the patch. By early evening, everyone was done and ready to go. The volunteers, especially the girls were very excited about getting their pictures clicked and were calling all of the major organizers (Rahul, Amit, Satya, etc.) to get their pictures clicked with them. It was pretty entertaining to watch.

This was followed by a cake, which was mostly eaten and the rest of it smeared on Rahul and Jared’s faces. To end the event, we had a feedback session with the volunteers and they gave us a few good tips on how we could have done some things better.

By the time we were back at Magarpatta City, everyone looked tired. Rahul had organized a parting dinner at the Cocoon for all the speakers and organizers, which was a lot of fun. I had a great time chatting with Heherson, Izhar, Arun S A G, Srishti Sethi, Anurag and Eugene Teo. After dinner it was time to head back home.

We did a lot of things right in this event and kudos to Rahul, Amit Shah and all of the core team for getting together a really great event. I hope that at least some of all of those college students make the transition from being users to being contributors, especially contributing code to Fedora and upstream projects.


FUDCon Pune 2011 Day 2: Me, followed by lunch, followed by me, followed by me...

The title pretty much summarizes what most of my day looked like on day 2 of FUDCon. Well, not exacly, but it comes quite close. I had three sessions lined up in a single day and I was worried that I might lose my voice by the end of it. Ankur Sinha had all of 4 talks in the single day, so I was definitely better off that him.

The day started with Harish Pillay’s keynote on the community architecture team. The turnout on day 2 was less than that on day 1, which was a little surprising. Most of them trickled later in the day, so it meant that a large number of the attendees in Harish’s talk were Red Hatters and the CoEP volunteers. We probably started a little too early for a Saturday.

Immediately following that was my session on qpid messaging. The attendance in the session was modest (about 8-10 people), but the best part was that they were very involved in the session and that made the session worthwhile. Mrugesh Karnik also joined the session mid-way and asked some really good questions that actually helped my session. We ended up doing a queue design for a fictitious stock trading system and I was able to show how the design could scale very easily with a qpid messaging broker in place. Unfortunately, most of the attendees did not have laptops, so I could not engage them in a hands-on session. In fact, that was my story of the day to a large extent. I had intended all my sessions to be hands-on, but most of it never really materialized because most of the audience did not have laptops.

After the qpid session, I spent some time chatting with Sankarshan, Mrugesh, Anurag and Nisha over lunch. After that I decided to double-check my exploit code samples because it was the one session that I had never done before and it was something that is not my area of expertise. The only aspect of the exploits that I was really comfortable with was how they worked and how I could explain that using the usual tools like gdb, objdump, etc.

I was sitting in the speakers lounge cleaning up my examples when Aditya Patawari came in and asked me about my session. That reminded me that I had to actually go into the session :D We quickly left for the classroom and found pjp finishing up his python session, which had a packed audience. Once he was done, a lot of people left, which led me to think that even this talk was going to have a modest audience. However, people trickled in as I was about to begin and by the time I did begin, the room was full.

The exploits session was probably one of the best sessions I have done so far, mainly because I personally enjoyed it. The audience also consisted of people who were interested (exploits are sexy, as someone said later) and I got a lot of questions during and after the session. The talk also seemed to give some people from the audience the impression that I am a security expert, which is flattering but incorrect.

Then came the awesome part where Pai and Yogesh Babar followed up my session with impromptu sessions, which the audience lapped up eagerly as well. Pai talked about extensibility of postgresql by making it call routines in perl (typical dinosaur stuff ;) ) and Yogesh did a talk on kdump. I learnt later that Rahul Sundaram did something similar in one of the seminar halls by asking the audience to “ask him anything about Fedora and Open Source”. Pretty cool stuff.

After Pai and Yogesh were done, it was again time for me to get on to the platform for another session, this time on autotools. This was something I had done multiple times with the same examples, so it was pretty uneventful.

Day 2 was probably awaited by a lot of people for another reason – the FUDPub! We went to Park Estique near Vimaan Nagar for dinner. There was loud music and bling bling lights and food and drink. I enjoyed the food and drink; the lights gave my a headache and the loud music was, well, too loud. In any case it was fun chatting with people and having the really good food.

Like the first day, I did not get to attend any other sessions, this time for a different reason. I’ll probably submit less sessions in the next conference so that I actually get to attend other sessions and meet and talk to more people. I did meet a lot of interesting people on day 2, so all of that hectic schedule was completely worth it.


FUDCon Pune 2011 Day 1: The lounge monitor edition

So we’re on the final day of FUDCon Pune now and I realized that I hadn’t written about my experience at the event at all. The last two days were very hectic and I got only about 6-7 hours of sleep on both days altogether.

I arrived at the venue at 7:30 AM to help out with registrations. Satya was in charge of that and we did not have any hiccups there. People trickled in fairly slowly and hence it was easier than we had thought it would be. We had a good crowd in; going by the fact that the auditorium was about half full, thee may have been over 250-300 people in there. The auditorium capacity is 900.

After a quick welcome note from the CoEP management, we kicked off the event with Jared Smith’s keynote on Fedora. Jared came up with the familiar analogy of streams to explain the way Fedora and upstream communities interact. He talked about how community members could transition from users of Fedora to contributors in Fedora. It was a great talk in general. I had one personal bone to pick in that however, which is the kind of options conveyed to students as avenues to contribute to Fedora.

I have been interacting with students on and off for about 2 years or so now and also been noticing the avenues that students seem to prefer to contribute to Fedora. One of the things I have always been concerned about in this regard is the fact that most students seem to prefer being ambassadors and volunteers and generally doing as less code as possible. In that context, stressing about non-technical ways to contribute was not something I agree with. Of course, it is not something that is wrong with Jared’s message in the talk; it is the fact that the message may be received incorrectly that I am concerned about. This is also why I am generally more inclined towards doing technical sessions instead of broad talks especially if students are the audience.

Anyway, so that was pretty much the only talk I attended, since I was the designated hall monitor for the speakers lounge. My job was to make sure that things run smoothly there and help speakers if they needed anything. While sitting there, I decided to work on the code for my exploits demo. I had wasted about 4 hours last night trying to get the shellcode exploit to work. I had found out in the end that the gold linker builds binaries without execute permissions for the stack and to et an executable stack, I would have to provide ‘-z execstack’ as an extra argument to the linker.

Huzaifa and Eugene Teo came in while I was working on this and Huzaifa introduced me to Eugene. This gave me a chance to pick their brains about the stuff I was about to do in the exploits workshop. Huzaifa pointed me to a few resources and also gave tips about various things I could add to my session to make it more complete. I gave up working on this after the crowd in the lounge increased and returned to chatting with people, some who I was meeting after a long time and others who I had met for the very first time.

I occasionally walked over to the sessions happening nearby to see how things were going and was pleasantly surprised that these sessions had good attendance too. I was concerned about the fact that we may find it difficult to direct attendees to the classrooms since they were a good 5-7 minute walk from the main auditorium and the seminar halls. On the contrary Arun Sag’s introductory session on Linux and Linux commands was hugely successful with the classroom being packed full.

So the first day of FUDCon was a good day of meeting friends for me. The second day was very hectic too and I will write a separate post about it since now it is time for me to work on Kushal’s libgqpid.


FUDCon Pune 2011: Less than 48 hours to go!

Firstly,

and I’ve got a lot of things to do once I’m there!

FUDCon Pune 2011 has a wonderful line-up of talks and sessions going for it this weekend. I have added three workshops of my own too:

  • Getting started with autotools: This is intended to be a hands-on session on autotools. I have done this session multiple times before and it has been quite successful with beginners looking to understand the GNU build system.
  • Security exploits, Live!: This was originally Amit Shah’s idea, since he wanted someone to do a demo of buffer overflows and similar stuff. You don’t really have to be an aspiring security professional to attend this, since most of the ideas are based on basic programming fundamentals
  • Apache Qpid messaging: “Enterprise Applications” are not typically things that you deal with when you’re in college. Quite often one ends up thinking of these things as inaccessible due to high costs and high perceived difficulty level. In this session, I intend to demonstrate how easy it is to write really complicated applications with mind-blowing ease.
I finally got involved in preparations for FUDCon this week to try and help wherever needed. Rahul suggested I help out with the schedule arrangement, since I had some ideas on the layout of some sessions. We slugged it out for about 4 hours yesterday and another 3 hours today at the Red Hat office, trying to make sure we schedule talks in a manner that attendees can follow tracks (virtualization, security, web apps, embedded, etc.) and at the same time, have enough flexibility to add talks and sessions without having to shuffle things around all the time. Saleem has become a pro at copy-pasting across cells in spreadsheets as a result.

The end result is pretty impressive and we’re expecting even more submissions to keep people busy. There were concerns on whether there were too many sessions running in parallel, but I don’t think that matters. The event attendance is expected to be quite large, so there will e enough audience to keep all speakers busy. Besides, I don’t know a single conference where one gets to attend each and every talk in the conference. The real fun of the conference is to meet friends, collaborators and fellow geeks and not just sitting in rooms and listening to people talk.

Oh, and we have hackfests throughout the day on Sunday. The one I am particularly psyched about is Kushal Das’ libgqpid. It was an idea we had brainstormed about earlier and he wrote a lot of the code in it. Hopefully we can get a release out on Sunday with the core qpid client features ready. For the uninitiated (which is pretty much everyone I guess, since Kushal has not published the code yet), libgqpid is a glib based C wrapper around the qpid C++ client.

Looking forward to having a great time at FUDCon!


Moving on

I have finally moved my website content over to dreamhost. The Net4 account has been utter nonsense, with its idiotic control panel and silly pricing. For more or less the same price, I am hosting two websites on dreamhost with unlimited email aliases, subdomains, mysql database, host of apps and a really good control panel. Livejournal has been fairly sucky too lately with its random downtimes, ads and loads of comment spam.

Everything looks pretty much the same right now, but I’ll soon start making changes. I will send requests to update planet links (at least wherever I know I am syndicated) once I have everything in place. I need to write up a bit on the couple of sessions I’ll be doing at FudCon Pune. this coming weekend, hopefully by tomorrow.


Preparing for FUDCon -- Fedora Activity Day

September has been a very busy month for me with Siddhi going to UK for her studies, Mom moving in with us and my role change at work. In all of this confusion, a Fedora Activity Day (FAD) was planned for 10th September. I had to skip it because I had to go to Mumbai to spend the week with Siddhi before she left for Manchester. (Un)luckily, that FAD was rescheduled because of some last moment issues at COEP and it finally happened today at our office.

This FAD was planned to be something of an initiation for students so that they could do much more at the FUDCon than just attend talks. Going with that theme, I pitched in to do a rerun of my autotools demo that I had done last year, and even in the Fedora classroom. It is one of the basic things that a Fedora packager ought to know and if we're doing sessions on packaging, we might as well throw in some autotools foo.

There were a bunch of talks planned, mostly by Rahul Sundaram and Shakthi Kannan and then some by me, Prasad, Kashyap and Shreyank. But only a few of those talks actually happened. Essentially, since I came in, only I, Shakthi and Rahul spoke at all.

To begin with, I was late. According to the schedule, the talks were to happen in two meeting rooms in parallel and me and Shakthi were to do the autotools demo in parallel in both rooms. But when I reached office, I saw that there were enough to fit into one large meeting room, so scheduling talks was going to be easier.I had missed Rahul's first talk and he had already begun talking about packaging. Rahul walked everyone through the process of packaging the hello world app. After joking around a bit with Pai and Kushal, I joined Kushal and Shakthi in helping those who got stuck in the packaging demo.

Lunch followed the rpm walkthrough and we literally destroyed the pizzas that came in - there weren't enough in the end and we had to order a few more pizzas.

While the pizzas were being delivered, Shakthi walked everyone through version control using git. The main theme was managing love letters to various bollywood superstars using git. Pretty entertaining :)

After the second lunch break (where more pizzas were quickly destroyed), I was to start my demo on autotools. Before it started, Pai and Kashyap had a couple of quick 2 minute talks. Kashyap because he was asked by a number of attendees on how upstream, Fedora and RHEL were related. He showed a quick 1 minute video in which Paul Frields explained how bits come in from upstream into Fedora and finally into RHEL and how engineers from Red Hat are involved at every stage with the community. Pai wanted to gauge audience interest in databases and their role in ERPs -- there were a fair number of people who were interested, so we might see a talk from him on those lines at the next FAD.

My autotools walkthrough ended up being the last thing on the agenda because I (just like the talks before me) took more time than was allotted to me to finish. We finished with some good feedback and suggestions for improvement from the audience.

The best takeaway from this session was the involvement of all of the students who attended today's FAD. The schedule was quite gruelling and all of the walkthroughs were very intense. Despite that it was refreshing to see all of them putting their heads down and giving it their best, asking good questions and not giving up at any stage. I am hoping that we will have a similar if not better response in our next FAD in October.


My first program on my Samsung Galaxy S

No, it is not a java program, it is in assembly, which was possible because I recently flashed Cyanogenmod on my phone. Here it is:

.text
.global _start
_start:
    mov r7, #1
    mov r0, #42
    swi #0

The program simply returns 42 and exits. I used my own cross-built binutils (--target=armv-android-eabi) to build this and simply copied it over to my phone, chmod and executed it. You need to put it outside your sdcard environment however, since you cannot execute anything in /sdcard. A Stackoverflow thread helped figure out the right opcode for the syscall.

It took me all of 6 hours to figure this out. 5 minutes to figure out the above code and 5 hours and 55 minutes to realize and fix the last line from

swi 0

to

swi #0

Changing the default loader for a program in its ELF

I was following an email thread in the libc-help mailing list, where the OP asked how one could force a program to load with a different loader, i.e. a loader from a different build of glibc. The answer, which is available if you follow the thread, is that it is necessary to rebuild the program to do this, with the --dynamic-linker switch to the linker. The best answer for the thread was to do this without a rebuild by making a wrapper script that invokes the program with an alternate loader, like:

/path/to/other/ld-linux.so program_name

So the story should have ended there. But it got me thinking; how hard could it be to edit the program to change the hard-coded loader value in the program? So I decided to find out.

The first try was as simple as replacing the string with my new loader string in a test program, which is basically just a Hell Oh World program. To do this, I opened the binary in emacs and changed to hex mode using M-x and then hexl-mode. Next I just wrote over the string with the absolute path of the new loader. I saved my changes and ran the program:

[siddhesh@localhost ~]$ ./a.out
bash: ./a.out: cannot execute binary file

Obviously I had done something wrong. So I had to do a bit of reading to understand what all was to change. One very obvious thing about this was that the length of the loader string was being recorded somewhere -- I was prety sure I had not overwritten anything and I had not changed the offset of the string at all. So I started reading the System V ABI documentation, which includes information on the ELF header. The ELF header documents where the program header table is, and the size of each program header table entry. one could read this very easily using the elfutils readelf command. So here's what I got:

[siddhesh@localhost ~]$ readelf -h ./a.out
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x4003e0
  Start of program headers:          64 (bytes into file)
  Start of section headers:          2472 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         8
  Size of section headers:           64 (bytes)
  Number of section headers:         30
  Section header string table index: 27

So the important information here is the start of program headers and the size of each program header. In the case above, the program header starts 64 bytes into the file and then every 56 bytes after that was a program header. You can also read the program headers using elfutils:

[siddhesh@localhost ~]$ readelf -l ./a.out

Elf file type is EXEC (Executable file)
Entry point 0x4003e0
There are 8 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040
                 0x00000000000001c0 0x00000000000001c0  R E    8
  INTERP         0x0000000000000200 0x0000000000400200 0x0000000000400200
                 0x000000000000001c 0x000000000000001c  R      1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x000000000000068c 0x000000000000068c  R E    200000
  LOAD           0x0000000000000690 0x0000000000600690 0x0000000000600690
                 0x00000000000001ec 0x0000000000000200  RW     200000
  DYNAMIC        0x00000000000006b8 0x00000000006006b8 0x00000000006006b8
                 0x0000000000000190 0x0000000000000190  RW     8
  NOTE           0x000000000000021c 0x000000000040021c 0x000000000040021c
                 0x0000000000000044 0x0000000000000044  R      4
  GNU_EH_FRAME   0x00000000000005e8 0x00000000004005e8 0x00000000004005e8
                 0x0000000000000024 0x0000000000000024  R      4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     8

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .interp 
   02     .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame 
   03     .ctors .dtors .jcr .dynamic .got .got.plt .data .bss 
   04     .dynamic 
   05     .note.ABI-tag .note.gnu.build-id 
   06     .eh_frame_hdr 
   07     

The relevant section here is the INTERP section. Each program header is basically this struct:

typedef struct {
        Elf32_Word p_type;
        Elf32_Off p_offset;
        Elf32_Addr p_vaddr;
        Elf32_Addr p_paddr;
        Elf32_Word p_filesz;
        Elf32_Word p_memsz;
        Elf32_Word p_flags;
        Elf32_Word p_align;
} Elf32_Phdr;

Here, the relevant values of the string size are p_filesz and p_memsz. If you look into the values from the readelf, you'll see that the size is 0x1c, which is the length of the string, including the trailing null character. So that is what I had to change. Now I had to find this header in the hex editor. The header is the one beginning with PT_INTERP, which has value 0x03:

87654321  0011 2233 4455 6677 8899 aabb ccdd eeff  0123456789abcdef                                                                                                               
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000  .ELF............
00000010: 0200 3e00 0100 0000 e003 4000 0000 0000  ..>.......@.....
00000020: 4000 0000 0000 0000 a809 0000 0000 0000  @...............
00000030: 0000 0000 4000 3800 0800 4000 1e00 1b00  ....@.8...@.....
00000040: 0600 0000 0500 0000 4000 0000 0000 0000  ........@.......
00000050: 4000 4000 0000 0000 4000 4000 0000 0000  @.@.....@.@.....
00000060: c001 0000 0000 0000 c001 0000 0000 0000  ................
00000070: 0800 0000 0000 0000 0300 0000 0400 0000  ................
00000080: 0002 0000 0000 0000 0002 4000 0000 0000  ..........@.....
00000090: 0002 4000 0000 0000 1c00 0000 0000 0000  ..@.....(.......
000000a0: 1c00 0000 0000 0000 0100 0000 0000 0000  (...............

I just changed the highlighted 1c to 28, which is the hex value of the string length of my interpreter (/home/siddhesh/sandbox/lib/ld-2.8.90.so). This and the change in the string was all that was needed to change the interpreter for the program. This has one really basic flaw, which is that if the interpreter string is longer than the current available space in the header, I will end up overwriting other data, thus corrupting the binary. So if you're being adventurous, be sure that your interpreter path is small enough to fit into the available space.


Comments are closed.