Runtime Process Infection (part 1)
This is a modal window.
Das Video konnte nicht geladen werden, da entweder ein Server- oder Netzwerkfehler auftrat oder das Format nicht unterstützt wird.
Formale Metadaten
Titel |
| |
Serientitel | ||
Anzahl der Teile | 26 | |
Autor | ||
Lizenz | CC-Namensnennung 3.0 Unported: Sie dürfen das Werk bzw. den Inhalt zu jedem legalen Zweck nutzen, verändern und in unveränderter oder veränderter Form vervielfältigen, verbreiten und öffentlich zugänglich machen, sofern Sie den Namen des Autors/Rechteinhabers in der von ihm festgelegten Weise nennen. | |
Identifikatoren | 10.5446/19176 (DOI) | |
Herausgeber | ||
Erscheinungsjahr | ||
Sprache |
Inhaltliche Metadaten
Fachgebiet | ||
Genre | ||
Abstract |
|
1
2
7
8
10
11
13
14
15
18
19
20
21
00:00
Lesen <Datenverarbeitung>LaufzeitfehlerServerHackerBenutzerbeteiligungWeb-ApplikationComputersicherheitPhysikalische TheorieSoftwareschwachstelleCoxeter-GruppeWeb logSpezialrechnerBitVirtuelle AdresseSpeicherverwaltungInformationEinfache GenauigkeitExploitMetropolitan area networkZweiFächer <Mathematik>StrömungsrichtungTwitter <Softwareplattform>SichtenkonzeptHalbleiterspeicherGreen-FunktionProgrammierungHyperbelverfahrenMAPFirewallBinärcodeMultiplikationsoperatorProgrammierparadigmaThermodynamischer ProzessNabel <Mathematik>InstantiierungDemoszene <Programmierung>BimodulWahlfreier ZugriffAutorisierungQuaderEinfach zusammenhängender RaumMailing-ListeNatürliche SpracheDienst <Informatik>DifferenteRotationsflächeNeuroinformatikVerkehrsinformationFehlermeldungZahlenbereichFront-End <Software>Projektive EbeneWeg <Topologie>SpywareVersionsverwaltungGewicht <Ausgleichsrechnung>p-BlockHochdruckReverse Engineering
07:21
Binder <Informatik>Kernel <Informatik>BinärcodeVirtuelle AdresseSechseckSpeicheradresseGarbentheorieZeiger <Informatik>TabelleMetadatenMultiplikationsoperatorArithmetisches MittelBitE-MailFront-End <Software>QuaderLaufzeitfehlerVererbungshierarchieReverse EngineeringRechenschieberMereologieAdressraumURLGrundsätze ordnungsmäßiger DatenverarbeitungDebuggingBefehlsprozessorEinfache GenauigkeitVirtualisierungExistenzsatzThermodynamischer ProzessPhysikalisches SystemLastCompilerTypentheorieEinfach zusammenhängender RaumHalbleiterspeicherGüte der AnpassungProzess <Physik>Nabel <Mathematik>Wurm <Informatik>ComputervirusComputersicherheitDateiformatSchnittmengeGamecontrollerWeb logDemo <Programm>CodeZeichenketteKeller <Informatik>ProgrammierungFunktionalDifferenteElektronische PublikationHook <Programmierung>Algorithmische ProgrammierspracheMultiplikationRechter WinkelCoxeter-GruppeAblaufverfolgungFreewareDatenstrukturFahne <Mathematik>DruckspannungFlächeninhaltEinfügungsdämpfungObjekt <Kategorie>StrömungsrichtungNatürliche SpracheKugelkappeTopologieFaserbündelSystemaufrufFormale GrammatikBildschirmmaskeOvalJensen-MaßWald <Graphentheorie>Computeranimation
14:41
MalwareLeckRippen <Informatik>DatenstrukturMetadatenTabelleInformationsspeicherungKernel <Informatik>Zeiger <Informatik>E-MailArithmetisches MittelExistenzaussageBefehlscodeFunktionalGraphische BenutzeroberflächeSystemaufrufHalbleiterspeicherSpeicherverwaltungProgrammbibliothekSoftwareentwicklerVererbungshierarchieRechenschieberCodeRechter WinkelPhysikalisches SystemBetriebsmittelverwaltungStrömungsrichtungThermodynamischer ProzessEin-AusgabeMini-DiscKeller <Informatik>MatchingNichtlinearer OperatorMultiplikationsoperatorRadikal <Mathematik>AusnahmebehandlungWurzel <Mathematik>Inhalt <Mathematik>BildschirmfensterFlash-SpeicherInverser LimesGrundsätze ordnungsmäßiger DatenverarbeitungCursorProgrammierungAblaufverfolgungPunktNatürliche SpracheGrenzschichtablösungTouchscreenDatenloggerQuadersinc-FunktionNabel <Mathematik>Kartesische KoordinatenSicherungskopieDifferenteTeilbarkeitGruppe <Mathematik>
Transkript: English(automatisch erzeugt)
00:00
Welcome to runtime process infection. My name is Sean Webb, and I go by the handle Ladara online. This presentation is brought to you by a hacking community called Soldier X. They deal mostly with reverse engineering, and they've got a lot of talented folk on their crew.
00:23
So this is the first time I've given this presentation up in Canada. And while my roommate up here was getting ready for the day, I turned on the TV, and the first thing I saw was Red Green. Do we have any Red Green fans in here? A few.
00:42
So because I grew up about three hours away from Canada south in Washington state, a major Canadian influence, and I love Red Green. So I'm going to start this presentation off with the man's prayer. I'm a man.
01:01
I can change if I have to, I guess. So I am just another tech blogger on the inner tubes. I run a small tech blog called 0xviewface.org, and I just blog about things that interest me, things that I'm doing, mainly about security
01:23
and FreeBSD and IPv6. I am the author of a Drupal module that makes administrating VNet jails really, really easy. So yeah, I'm a professional security engineer.
01:43
I've been working professionally in the security scene for a number of years, and I just love it. It's my passion. As a hobby, though, I've been programming in C for 13 years. I'm still a bit of a noob, but I'm pretty decent.
02:04
So I'm a member of Soldier X, Binary Revolution, and Hack3R. They are hacker communities that are kind of similar to each other, just a lot of kids who love to program and do different things.
02:22
You can find me on Twitter. My handle is Latara, and I frequent Freenode IRC. I'm on the FreeBSD channel. I'm supposed to give a shout out to them. So I do have a few disclaimers, though. Of course, opinions and views expressed here
02:43
are mine only, and not that of my employers. My previous employers, current employer, or future employers have to say that to cover my butt, and theirs too. My talk is semi-random. There's a lot of background info that I need to explain, so it's going to appear semi-random,
03:00
but it'll all make sense in the end. We're going to tie every single piece of background information together. So almost nothing new is explained. The theory, the underlying theory, is very well known. And understood. Runtime process infection, that's how malware works. You can take a look at a lot of the basic theories
03:25
on Frac, Google for runtime process infection. You'll get a whole bunch of, you'll get a nice big reading list. I do have a new spin on existing techniques for getting your shellcode to be stored and run.
03:41
So even though the underlying theory is very well known, I do have a new spin on existing techniques. The presentation and tools that I'll talk to you guys about is only for educational purposes only. Again, this is just to cover my butt. I'm not responsible for anything you guys do. And really, this presentation's kind
04:01
of a high level presentation. So there's not really much that you can do with the presentation material. I do make a few assumptions. We're at BSD can, so I assume you know what FreeBSD is. I assume you have a basic knowledge of C and 64-bit memory
04:23
management. So I assume you know what the printf is, what malloc is, and map, that kind of stuff. And I assume you know what a memory mapping is, a heap and a stack, that kind of thing. As security engineers and analysts,
04:41
we have to think abstractly. We have to think outside the bun. Think of how the original engineers designed what we're looking at and figure out how to use that and utilize it in ways that they didn't originally intend. The presentation does assume a non-modified memory layout.
05:02
GR second packs, of course, don't exist on FreeBSD. But the concepts are similar. I assume no ASLR, essentially, just to make the presentation easy. So to give a little bit of history, a few years back, I was looking at CGI and web application vulnerabilities.
05:22
My main purpose was to get a shell on the box. So I would utilize connect-back shellcode. So when I would gain a shell on the box, what would happen is, on my box locally, I would run netcat and have it listening on the port. And the shellcode that is running
05:41
on the victim, on the target box, would connect back to my netcat instance and drop me into a shell. So I needed reliable random access. Of course, this kind of paradigm doesn't really work if I'm at McDonald's, if I'm at a friend's house, if I'm at a hotel.
06:02
No matter what, I need to be able to forward a port to my local computer, which doesn't really work firewall holes or a bit of a problem. So I figured the web server's already listening for a port. So let's reuse that existing connection to the web server.
06:23
I also needed a way to covertly sniff traffic. There was one instance where I needed to get at some traffic that was encrypted with SSL. And I needed the decrypted version of the data. So I created a tool called libhijack.
06:40
And we'll talk about libhijack a little bit later. So to set the stage for this presentation, we're going to pretend as though we got a shell via a CGI or web application exploit. And we're primarily looking for a reliable way to get back in.
07:03
NGINX is a good candidate because I say NGINX here because Apache has some extra security things. Back when I was originally looking at this, they didn't. And my original target was Apache, but now it's NGINX because NGINX doesn't have the same security
07:21
settings or security code practices that Apache does. So we'll do a live demo against NGINX today after the presentation. So I thought it was a good candidate because it's already
07:42
listening for connections. So my main goal then is to modify the NGINX process somehow to run a shell when I send it a special string. So when I send it get slash shell, HTTP slash 1.1, it needs to drop me into a shell.
08:01
And I could run the who am I command, and it would tell me I'm www. So we need to be able to hook certain functions in runtime. So any time NGINX receives this string, it will drop me into a shell. So it has to happen multiple times because I might connect to this box multiple times.
08:25
So now we're going to talk a little bit about what happens when execve is called, when a process is loaded. The kernel first checks for very basic stuff, whether the file's there and whether you have permission to run it. Then it loads what is called the runtime linker, the RTLD,
08:42
for short. And then it loads all the process metadata and initializes the stack. Those two things are kind of reverse. It first does the process metadata and initializes the stack, and then does the runtime linker. Didn't have time to reverse that. Anyways, the metadata is located at that hex address
09:04
on the FreeBSD and B64. I have that there really. Wow, that's cut off on the right side. Is there a way to fix that? OK. OK. Is there any way to fix that?
09:21
Probably you guys can. OK. Well, you guys, it's OK. I'm saying what needs to be said anyways. Yeah, we're good. I included that hex address on the slides because I'm going to put the slides up on my tech blog so you can have an easy place to reference.
09:44
So the runtime linker, its job is to finish loading the process into memory. It loads all the dependencies, all the shared objects, like libc, if you're Wireshark, libpcap, that kind of thing. It then patches what is called the procedure linkage table and global offset table for needed dynamic functions.
10:04
We'll talk about the PLT GOT a lot in detail later. Then it calls all the initialization routines for all your dependencies. And then it finally turns control over to your intended process. It calls main.
10:21
Elf, best Christmas movie ever. I'm big on the Christmas, and I start watching in November. It drives my wife insane, but I love it. Francisco. Elf stands for the executable and linkable format.
10:41
All it is is it's metadata. It's just data that describes data. It tells the runtime linker what to load and how to load it. So you have different header files, or rather C structs. So if I say not header files, you have different headers.
11:03
If I say header, I mean C struct. That's what I mean. So you have the main elf header, and that has pointers to other different headers. Some of those different headers are the process header, which you have to have at minimum one entry for your binary to be valid.
11:24
It contains virtual address locations. So where in memory is this data going to be stored? Access rights, whether you can read from it, write to it, or execute it. And alignment. Where inside of this virtual address location is it going to be located? Is it going to be in the beginning, in the middle,
11:41
in the end? That type of thing. Then you have section headers. You don't have to have any section headers. In fact, when you strip a binary, you pretty much strip out all the section headers. It describes the data that is loaded via the process headers.
12:00
It contains a string table, debugging entries if any, and compiler comments. Fun little trivia, old school viruses used to store their payload inside of compiler comments. So there's the dynamic headers as well. Those contain relocation entries, stubs,
12:20
and the PLT GOT, the procedure linkage table, and global offset table. And that's really the jackpot. That's where all the magic happens. This is how an elf binary looks in memory when it's loaded. So at the top, you have the main elf header. And right below that, you have the program header table,
12:42
also called the process header table. And then you have the actual data that is used by the program, your read-only data, your executable code, all that kind of stuff. And the section header, those may or may not get loaded at runtime, depending on how
13:03
that binary was constructed. And how it's instructing the runtime linker how to load itself. So debugging, ptrace is the old school debugging facility for FreeBSD. I say old school because it really ought to be replaced outright with dtrace.
13:22
So dtrace is much cooler, but we're going to use ptrace because it's still available. It is a kernel system call. And GDB, the GNU debugger, relies heavily on ptrace. Ptrace is the back end for GDB. It's how it's able to do its magical debugging work.
13:43
You can read and write from and to arbitrary memory locations. But that memory location has to be valid. So you can't just write to a memory mapping that doesn't exist. It has to actually exist.
14:00
You can get and set all the registers, the current instruction pointer, the e-flags, every single register, every single CPU register can be changed with ptrace. So essentially, with ptrace, you're God. When you attach as a debugger to another process using
14:21
ptrace, you can change every single part of the program. And so this next bullet, debuggy, becomes child of a debugger. That's a little bit important as far as terminology is concerned because we're going to, in the presentation, I'll say parent or child relationship.
14:42
And I'll be the counselor between the two. But let's say I'm a Firefox developer and I want to debug one of the memory leaks that so plague Firefox. And so I have Firefox already running. It's on Homestar Runner downloading
15:01
a whole bunch of Flash content. And then in a terminal on the other screen, I've got GDB loaded up. So we have Firefox and GDB. They were started at completely separate points in time. They're unrelated to each other. They were started in different manners. So they're completely unrelated.
15:21
But when you attach GDB to Firefox, then Firefox conceptually becomes the child of GDB. It's as if GDB were to have spawned Firefox itself. So when I say the parent process,
15:42
then I'm talking about GDB or about libhijack. And if I'm talking about the child process, then it would be Firefox or nginx. And it's destructive. A user is going to know. If you're using ptrace against a GUI application,
16:01
for example, a user will notice that something's happening. The process just pauses there. If you're in Firefox and you click on a text box, nothing will happen. Not even a little cursor will display. The process is completely paused, so it's destructive.
16:21
And this probably isn't true, but I like to think so. The original ptrace engineer, I like to think, is evil as an evil genius. Likely knew he could be abused because you really are God over a process. You can change. I mean, you could switch out nginx and have it run LS instead.
16:41
Technically, you could do that, but you could. And ptrace is pretty powerful. There is one limitation in that. You can't use ptrace against any process unless you're root. If you're root, you can call ptrace against any process on the system,
17:00
except for the init process. But if you are not root, then you can only call ptrace against processes that you own. So processes whose uid matches your uid. So there are some current techniques for getting your shellcode stored and run. The first and originally very, very popular way
17:21
was to store your shellcode on the stack. And that was really, really made popular by a guy named Aleph1, who wrote an article for Frac called Smashing the Stack for Fun and Profit. You all probably know about that paper in this room. But yeah, it was really popular. Because of its popularity, on most systems today,
17:44
the stack is non-executable. You can store your code there. You can store your shellcode there all you want, but you're not going to get it to run. You can store your shellcode at the current instruction pointer at RIP. But the problem with that is that it mucks up
18:00
the original code. You can only get your shellcode to run once, because what you need to do then is back up the original code that was originally executing, overwrite it with your malicious shellcode, and then run your malicious shellcode, and then restore the backed up code.
18:21
And that doesn't really work for our purposes, because if you do that, you only get your shellcode to run once. We need our malicious code to run multiple times. Every time data is received and it matches that string, that special string, we need to drop into a shell. So clearly, though this would be nice,
18:42
it's a guaranteed spot where you have guaranteed execution. But it just won't work for us. You could store your shellcode on the heap, and that used to be very popular. And although it's not as popular today to make the heap non-executable,
19:01
it's becoming so. You could use LD preload, but chances are we just pwned a non-root process. And we don't want to gain root, because if the system is properly configured, there's probably log files, IDS,
19:20
that says only certain processes can run as root, and maybe only at certain times. So and the process has already started. We would need to restart the process, meaning gain root. So we have this arbitrary code to store. We have the shellcode to store, but we can't store it anywhere.
19:42
Where do we do it? What we're going to do is we're going to force the child process to allocate memory. And this is the new spin. This is the slightly new technique. Unlike Windows and OS 10, we cannot allocate in behalf
20:00
of the child inside of the parent process. The child must be the one to allocate. And that's kind of a problem, because the child is probably just waiting on disk access or network access or input from the user. And so though it might allocate memory right now, it's only going to allocate memory
20:21
in the stack or in the heap. It's not going to allocate something we can use for our purposes. So that presents kind of a problem. So what we're going to do is we're going to find where the kernel is called inside of this program. We're going to look for the assembly syscall opcode.
20:42
And the problem is that the program's main code won't ever call the kernel. It'll call library functions which call the kernel, like libc. Libc calls the kernel everywhere. Like when you do printf, it actually has to write stuff to the console, which is actually
21:02
a privileged operation. The kernel has to be the one to do all that. So what we'll do is we'll find a library function that calls the kernel by crawling through all this ELF metadata by going through all these ELF headers and parsing them out.
21:25
So the main ELF header contains a pointer to the process header. And the process header contains a pointer to the dynamic headers. And the dynamic headers contain a pointer to the GOT, the global offset table.
21:41
And the second entry of the global offset table contains a pointer to the OBJ entry structure. And I say second global offset table entry here. The slide says 1 because we're starting at a 0 offset. So 0, 1. And the OBJ entry structure.