Log in

View Full Version : Shared object injection on linux/unix


Quake2
November 13th, 2008, 06:18
Hi, I'm almost new here
I've been pointed here by a friend of mine (hi Daniel ) who suggested me to post to this blog.

In the past few weeks, being a little bored I've done some research on Linux and tried to do the usual weird things done by reversers. So I've researched a bit the field related to code injection, which is a topic almost never discussed on Linux (at least, I've found really few topics on it) and on other UNIX-like systems (mainly FreeBSD and OSX, since they're the most popular ones).

So to summarize the results obtained so far I've written an article divided in two parts (the first is out, the second will come out in the next few days), the first one is just an introduction to the ELF file format and some observation on its loading phase.

The first part can be found here: http://lamp.codeproject.com/KB/cpp/shared_object_injection_1.aspx
I've hosted it on codeproject since I don't own any webspace, but their article submitting facility really sucks and didn't allow me to post the attachment (which I attached to this post).

Now the first part might be a bit boring, since is just an introduction, but the next part will come soon. Anyway, let me know what you think about this research topic.

There's a lot of things that needs to be cleared on this topic, unfortunately there's not much informations about them (you might say "read the source code", eh... not an easy thing on Linux and anyway reading the source takes too much time), here's some points that needs discussion:

1) why uselib() syscall does not work anymore from 2.6 kernel? Actually calling it always returns "Invalid object file format"

2) since the /proc filesystem is being slowly replaced with the /sys filesystem, is there anyway to obtain the memory map of a running process other than relying on these filesystems?

3) since most UNIX systems lack the /proc filesystem, how to obtain the memory map on them? There's a lot of information on undocumented and unsupported ways to do it, but undocumented things are always evil (moreover on linux, where they keep changing at an insanely high rate )

4) reliability of the ptrace interface, on OSX it has been heavily modified to avoid tracing applications which make use of DRM (actually hacking the kernel with a kext will remove this limitation, but in the kext you have to modify absolute addresses, which will easily change between kernel builds). On *BSD it seems to work, but I did not investigated much on it, what about Solaris? (which, anyway, is not a desktop-oriented system, so it has much lower priority on my list )

5) alternatives to ptrace? Actually ptrace is used to stop a running process, attach to it, reading/writing from/to its memory, int1/int3 breakpoint signaling. ptrace seems to be the only "standard" debug api amongst UNIX systems, any ideas?

6) what about processes which avoid being traced by forking themselves and using ptrace(PTRACE_TRACEME, ...) ? This works since looking at the implementation of ptrace(), we can see that if there's a process which is already tracing our target process, the second attach will fail, any ideas to bypass this?

my guidlines in this research are:

1) the priority is that it works on Linux, then OSX, then any other UNIX, but the important ones are Linux and OSX.

2) it should make use of standard and well-documented interfaces, so they won't change in the near future

3) on Linux, it should work across different distributions, so it should not rely on functions which are patched for a particular distro..., this is not a problem on OSX, since actually almost everyone has upgraded to Leopard

4) the most important one, everything should be "privilege-free", I mean, actually the technique I use works without being root or using some privilege-escalation techniques, since with ptrace, a user can attach to his own processes, which is what I want

5) the LD_PRELOAD method should be avoided as much as possible, since it requires the process to be restarted and will not work on setuid(0) executables.

so, any informations, links, bits of text, "Once upon a time a friend of mine told me...", everything you might ever have heared about this...is really appreciated , I'm trying to collect as much informations as possible

I'll update this blog entry as soon as the second part comes out and I will keep it updated as I start my reseach on OSX, which will come after I've done with Linux...

This will be a slow research, since I'm doing it on my spare time, but I thought that it would be nice to start sharing the results, you know...I'm a scientist and collaboration is at the heart of science and progress

Thanks for your time reading this, see you next post

Attached Files
Quote:

http://www.woodmann.com/forum/attach/zip.gif
so_inject_1.zip ("http://www.woodmann.com/forum/blog_attachment.php?attachmentid=21&d=1226572188") (5.8 KB)

Daniel Pistelli
November 13th, 2008, 07:07
Quake2 is a close friend of mine and one of the most skilled people I know in the IT world. He hasn't written a paper in a very long time. He comes, like most people here, from the Windows world. So, this paper is meant to be understood by people who have no deep knowledge of the linux kernel or the elf format. In fact, the introduction to the elf format may be useful even for things other than injection. I told Quake2 to post here because in my opinion this is the best reversing (and IT) forum around. I hope someone finds the topic interesting.

ZaiRoN
November 13th, 2008, 07:45
Benvenuto Quake2

Nice introduction, waiting for the next part!

Camus SoNiCo
November 13th, 2008, 08:58
Piacere & Thanks. This is a great idea to move on. I wanted to do so, and I'll be glad to follow and help asa i can.

Keep up

pnluck
November 13th, 2008, 10:20
Great paper! Now I can learn more on elf and linux programming.

dELTA
November 14th, 2008, 15:09
Thanks for the writeup Quake2, and welcome to the board!

Looking forward to the next part (and to have you participate in the forums in general, if you'd like).

And thanks Daniel for the "referral". (and I hope the new Explorer Suite project is going well, just too bad it takes much of your time from writing your usually great posts around the board ).

Daniel Pistelli
November 15th, 2008, 20:28
Yes, delta, it is true that I spend a lot of time on that project. However, I will be soon releasing a VERY long new article about C++. Since a part of the article shows Qt internals, I was thinking about re-using that piece of information to write a short paper about Qt reversing on the forum.

JMI
November 16th, 2008, 02:46
I'm sure many would find it useful.

Regards,

Quake2
November 16th, 2008, 11:10
Quote:
[Originally Posted by dELTA;77722]Thanks for the writeup Quake2, and welcome to the board!

Looking forward to the next part (and to have you participate in the forums in general, if you'd like).

thanks, I'll try to do my best
So little time, so many things to do...

anyway, I'm slowly progressing, recently I've been discussing about this topic with a colleague of mine, we came up with a solution which is valid for freebsd and (mostly) for osx, here's some details:

open up an handle to kernel image, with kvm_openfiles("/dev/null", "/dev/null", ...) thus it can be done by non-root users

get actual snapshot of kernel processes: kvm_getprocs, which returns an array of kinfo_proc

this is valid for both osx and freebsd. On freebsd the memory map can be retrieved by issuing a sysctl with KERN_PROC_VMMAP (this is a new sysctl, it's still not documented, so "man sysctl" will not show it, I've found it by looking at the source of procstat, which is a new freebsd utility), unfortunately there's no such sysctl on osx, so we're still searching...actually the utility vmmap from osx seems to do it (according to man it sholud use the vm_region syscall), but I'm searching for its source

this might not make sense at all, but believe me once you read the second part of my article everything will be much clear, I'm so sorry but I had not time to write it

anyway, I'll keep this post updated with every bits of informations I can find