Reversing Firmware With Radare

栏目: IT技术 · 发布时间: 5年前

内容简介:Hello everyone! Here’s a quick guide on reversing firmware w/Like most reversers, my experience with disassemblers started with compiled binaries. Loading these (barring strange circumstances) is pretty straightforward: you open the file in your disassemb

Hello everyone! Here’s a quick guide on reversing firmware w/ radare . Or, rather, loading firmware into radare; the process of reversing software in any disassembler is a little beyond the scope of any one blog post.

Background

Like most reversers, my experience with disassemblers started with compiled binaries. Loading these (barring strange circumstances) is pretty straightforward: you open the file in your disassembler of choice, the program reads binary info (architecture, entry point, etc) and goes to town. However, when I moved into embedded security, I found myself needing to analyze microcontroller firmware. This was more or less how that went:

Reversing Firmware With Radare

Fortunately a member of my team was gracious enough to train me up on doing the work in IDA and all was right with the world. However, recently I spent some time on leave and wanted to do some of the same work with open source tools. radare2 in particular had always scared me a little bit so I chose that to work with. I sat down with a firmware dump that I got out of a sketchy telematics dongle that I picked up, watched some radare2-related con talks, and managed to get the basics together.

I decided to write this because I prefer written instructional material and I couldn’t find any written guides with this level of detail. That said, I’ve opted to use asciinema videos to demo some stuff on the console in a few cases where I felt it worked better than screenshots; In my defense, I kept them short and they don’t need sound. :)

Note: I’m not giving any details of the dongle make or model, nor will I show any identifying pictures. Suffice it to say that it plugs into a vehicle’s diagnostic port and connects to a cellular handset.

The Objective

I’m gonna keep it simple: we just want to find the interrupt handler that handles received CAN messages. That’s it. It may not seem like a lot, but it’ll keep us going long enough for a medium-length blog post. :)

Trim the File

The first thing to do is to trim the relevant parts of the firmware file. This will help the auto-analysis take less time. The firmware dump was obtained in the Intel hex file format . I loaded it into r2 using the ihex:// IO plugin but, unfortunately, that plugin is broken at the moment so I had to convert it to a regular binary file.

Looking at the hex file, it looks like the lowest defined address should be 0x8000000 :

Reversing Firmware With Radare

Here, we confirm that and write out the defined data to a separate file:

Here we use the wtf! command to write from the current location (the start of defined data @ 0x8000000 ) to the end of the file.

Determine the Architecture

The next thing to do is figure out the architecture. In most cases, we could just look at the markings on the chip itself, but in this case the chip was covered by an RF shield. I searched the FCC ID to find relevant FCC filings, but in this case the images weren’t particularly helpful. Here’s a cropped image showing just the processor:

Reversing Firmware With Radare

If we squint, we can read “ARM” and not much else. But that’s something! Let’s figure out some other parameters using the p=i command, which shows the number of invalid instructions per block size. The basic process I used is to start twiddling asm values, namely asm.bits and asm.cpu (we already know asm.arch ), until we minimize the invalid instructions.

So as we can see, setting asm.bits=16 and asm.cpu=cortex seems to minimize the number of bad instructions.

Finally, if you comb through a strings dump from the image, you get this:

Reversing Firmware With Radare

Googling those model numbers will tell us that they’re both basically the same 32-bit ARM Cortex-M3 microcontroller. So why did the 16-bit setting work better than 32? The code is probably in Thumb mode, which r2 needs to be in 16-bit mode to handle.

Analysis: the first crack

So, just as a reminder, we’re trying to find the CAN interrupt handler. To do that, we have to find the Interrupt Vector Table (IVT). If we check the processor documentation, we see that the interrupt vector table should be at 0x8000000 . Here’s what the address at 0x8000000 looks like if we interpret it as an array of 32-bit words:

Reversing Firmware With Radare

That matches what the documentation leads us to expect. The first byte is an SRAM address, and all the rest are addresses in code flash. They’re all odd, which means that they’re all pointers to Thumb code , so that explains why we got the fewest invalid instructions with asm.arch set to 16.

So we’re good, right? WRONG! The CAN RX interrupt vector is at an offset of 0x90 . We notice in the figure above that the pointer is the same as all the other interrupt handlers, which is immediately discouraging. Not, however, as discouraging as when we look at the code it points to:

Reversing Firmware With Radare

Clearly, this is not the function we want, since it’s an infinite loop. But fear not! On this platform (and many platforms), the IVT can be moved by modifying a system register called VTOR at 0xE000ED08 . All we need to do is find crossreferences to that memory location, track writes to it, and we’re good. Right?

Let’s see how that pans out:

What happened here? There’s no xrefs here, even though we see the VTOR’s address in a few places that look like pointers. Well, when we load the file into r2 , r2 only knows about the memory addresses that we explicitly tell it about. In this case, that’s only a couple hundred kilobytes starting at memory address 0x8000000 . r2 doesn’t know anything about the address 0xE000ED08 , so it won’t track cross-references to it.

Feeding More Information to the Disassembler

So how do we tell r2 about those memory addresses? We define additional maps using the on command. We check the processor documentationagain to find the memory map, and find that SRAM comprises a 512M block starting at 0x20000000 , peripherals are another 512M block based at 0x40000000 , and Cortex peripherals (like the Vector Table Offset Register) are at 0xE0000000 . The general form I used for defining a memory block is like so:

on malloc://512M <base_addr> rw
omn <base_addr> <Name>

Typing all this in when we load the file into r2 is kind of tiresome, so I compiled all the asm directives and memory maps into a script file. By using the -i flag when invoking r2 , it will execute all of the commands after loading the file. You can find a copy of the script file here for reference.

And there it is! Now we can do some ~static analysis~ to figure out what this thing does with CAN frames.

So now what?

To be honest, I have no concrete plans for this thing. At this point I just poke at the firmware dump during the brief periods when my daughter is asleep. The next step may be to just take my newfound r2 skills on to other projects.

IDK though, who knows? I might adapt this thing to working with passenger vehicles instead of trucks.

Acknowledgements

Many thanks are due to @BenLGardiner , who introduced me to radare; I also cribbed some of this material from one of his workshops . Also to pancake , who gave a pretty good talk on reversing firmware with radare that got me started down the path.


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

算法引论

算法引论

[美]Udi Manber / 黄林鹏、谢瑾奎、陆首博、等 / 电子工业出版社 / 2005-9-1 / 35.00元

本书是国际算法大师乌迪·曼博(Udi Manber)博士撰写的一本享有盛誉的著作。全书共分12章:第1章到第4章为介绍性内容,涉及数学归纳法、算法分析、数据结构等内容;第5章提出了与归纳证明进行类比的算法设计思想;第6章到第9章分别给出了4个领域的算法,如序列和集合的算法、图算法、几何算法、代数和数值算法;第10章涉及归约,也是第11章的序幕,而后者涉及NP完全问题;第12章则介绍了并行算法;最后......一起来看看 《算法引论》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具