Skip to content

re-ws.pl

ReverseEngineering WorkStation

  • Home
  • Tutorials
  • Random
  • About

Tag: Reverse Engineering

Peugeot 407 rain sensor pinout

Posted on August 3, 2020 - August 3, 2020 by Kamil (aka. v3l0c1r4pt0r)
Paugeot 407 rain sensor

I had a project in mind featuring rain sensor, present in Peugeot 407 car, among others, probably. However, reality is that it is on my todo list for years now and I don’t think I will do it ever. But, I already bought the sensor in the past and it was lying in my drawer. So why not to disassemble it and figure out the pinout.

Identification

To be precise in what I am talking about, here are some magic values, I know about this thing:

  1. Manufacturer: Bosch
  2. Part number: 1 397 212
  3. Another number: 96 524 903 80
  4. Peugeot part number: 6405 CW

Continue reading “Peugeot 407 rain sensor pinout” →

Posted in RandomTagged 407, CAN, can-hacking, English, hacking, Peugeot, pinout, Reverse EngineeringLeave a comment

Playing with GF-07 GPS device

Posted on December 11, 2019 by Kamil (aka. v3l0c1r4pt0r)
GPS GF-07

GF-07 is dirt-cheap GPS locator. You put SIM card in it, send SMS and you know where it is. That’s it. But not for me. I like to know what I am using, especially if it is that cheap and such obscure device as this one. It comes together with manual that is written in so bad English that I barely understand anything. Immediately after opening SIM slot, one can see few test pads. Fortunately all of them are described in silkscreen. Let’s see what can be done with it as a one-evening hack.

GF-07 opened
SIM cover opened (pin headers visible)

Continue reading “Playing with GF-07 GPS device” →

Posted in RandomTagged English, GPS, GSM, hacking, hardware, Reverse Engineering18 Comments

LKV373A: radare2 plugin for easier reverse engineering of OpenRISC 1000 (or1k)

Posted on October 17, 2019 by Kamil (aka. v3l0c1r4pt0r)

This article is part of series about reverse-engineering LKV373A HDMI extender. Other parts are available at:

  • Part 1: Firmware image format
  • Part 2: Identifying processor architecture
  • Part 3: Reverse engineering instruction set architecture
  • Part 4: Crafting ELF
  • Part 5: Porting objdump
  • Part 6: State of the reverse engineering
  • Part 7: radare2 plugin for easier reverse engineering of OpenRISC 1000 (or1k)

For quite a long time I did not do anything about LKV373A. During that time the guy nicknamed jhol did fantastic job on my wiki, reversing almost complete instruction set for the encoder’s processor. Beside that nothing new was appearing. This has changed few days ago, when jhol published videos about the device. After that, someone found SDK that seems to match more or less the one used to produce LKV373A firmware. At the time of writing it was not available anymore. Although it provided a lot of useful information and what is important here, it gave a possibility to identify processor architecture. It turned out to be OpenRISC 1000 (or1k). Because it is known, I compiled binutils for that architecture. Unfortunately objdump, which is part of binutils is not the best tool for reverse engineering. Lack of hacks I made for my variant of binutils, which allowed me to follow data references, was making things even worse.

The conclusion was that I need some real reverse engineering tool for or1k architecture. Unfortunately, neither IDA Pro, nor Ghidra, nor radare2 does not have support for it, which is not so surprising, if I heard about it for the first time, when somebody identified LKV373A to have such core. Only few days later, I encountered good tutorial, explaining how to add support for new architecture. I didn’t need anything else.

I am not going to explain how to write disassembly plugin (called asm) for radare2. There are enough resources available. If one wants to try, my repository is quite nice place to start (notice template branch there).

Out of source build and installation

In radare2, it is possible to build plugins out of source. To do that in case of or1k plugins, repository has to be cloned first with usual git clone:

git clone https://github.com/v3l0c1r4pt0r/radare2-or1k.git

Then, inside of radare2-or1k, simply type make.

You should get two .so files in directory asm and anal. You can load them with r2 switch -l or from inside interface using:

L ./asm/asm_or1k.so
L ./anal/anal_or1k.so

Be sure to load both plugins, as lack of anal plugin leads to noisy warning shown with every analyzed opcode.

Final result should look more or less like below. This is the beginning of jedi.rom file:

            0x00000000      00000000       l.j 0x0
            0x00000004      15000002       invalid
            0x00000008      9c200011       l.addi r1, r0, 0x11
            0x0000000c      b4610000       l.mfspr r3, r1, 0x0
            0x00000010      9c80ffef       l.addi r4, r0, 0xffef
            0x00000014      e0432003       invalid
            0x00000018      c0011000       l.mtspr r1, r2, 0x0
            0x0000001c      18206030       invalid
            0x00000020      a8210088       l.ori r1, r1, 0x88
            0x00000024      9c400001       l.addi r2, r0, 0x1
            0x00000028      d4011000       l.sw r1, r2, 0x0
            0x0000002c      15000168       invalid
            0x00000030      15000168       invalid
            0x00000034      15000168       invalid
            0x00000038      15000168       invalid
            0x0000003c      00000031       l.j 0x100
            0x00000040      15000000       invalid

That’s it. Good luck with reverse engineering!

Posted in Reversing LKV373ATagged English, radare2, Reverse Engineering, software1 Comment

New VCI+A-BT (DS150E) ST-Link pinout

Posted on August 7, 2019 - August 8, 2019 by Kamil (aka. v3l0c1r4pt0r)
DS150E

This device could easily be found at the Chinese sellers. They advertise them as DS150E. Under the hood there is nice STM32 and STM8 pair. One is present on main PCB (in my case TCS MAIN V6.0), the other on relay board (TCS+RELAY V3.0). Both chips have their ST-Link headers broken out. If one want to read/write the firmware installed in internal flash, it should be as easy as connecting few of these pins. Continue reading “New VCI+A-BT (DS150E) ST-Link pinout” →

Posted in RandomTagged CAN, can-hacking, electronics, English, hacking, hardware, PCB, pinout, Reverse Engineering, STM32, STM82 Comments

PPPP API: what I know

Posted on May 10, 2018 - July 14, 2019 by Kamil (aka. v3l0c1r4pt0r)

While analyzing security of iMiniCam app, I learned some part of UDP protocol used to communicate with the camera. Here is quick bunch of facts.

UDP layer

Port 32100 (Proto_Hello, to external server) and port 32108 (others, to camera).

Type-length layer

Following structure represents first header that is always found in datagram.

struct header {
  uint8_t magic;
  enum proto_type type;
  uint16_t length;
}

In this structure magic is always set to 0xf1, type is one of the below values, packed on single byte and length count data that follows this packet, so if it is equal to zero, only those four bytes are transmitted. Continue reading “PPPP API: what I know” →

Posted in RandomTagged English, Reverse EngineeringLeave a comment

Security analysis of spy camera sold by Chinese suppliers: iMiniCam app

Posted on May 8, 2018 - July 14, 2019 by Kamil (aka. v3l0c1r4pt0r)
HD camera

Lately, I bought some random, noname spy camera from usual Chinese sources. Just after unboxing, one detail seemed a bit suspicious to me: together with the camera there comes a link to Android app, that is meant to control the camera. What is worse, the link leads to some Chinese app shop, obviously with only one language available (notice the version – 1.0.33, as it is not the only one in the wild):

http://m.app.so.com/detail/index?pname=com.hbwy.fan.iminicams&id=3646142

As I’ve already seen apps that i.e. calls home, despite having no need to open a single socket and then sending data like IMEI, IMSI, MAC addresses and so on, red lamp turned on and I said to myself: stop. Let’s reverse engineer the thing first!

OSINT

Before I begun my reverse engineering, I attempted to ask uncle Google (and his friends 🙂 ) to gain some knowledge. Usual virustotal gives me this:

Virustotal results for com.hbwy.fan.iminicams
Results of virustotal scan of original link

Continue reading “Security analysis of spy camera sold by Chinese suppliers: iMiniCam app” →

Posted in UncategorizedTagged Android, English, Reverse Engineering1 Comment

How to convert Android resource ID back into its name

Posted on March 27, 2018 - July 14, 2019 by Kamil (aka. v3l0c1r4pt0r)

Few weeks ago I made an attempt to reverse engineer some obscure Android APK. It was available only through some Chinese shop, obviously described in only one language there. Unfortunately, it turned out that every tool designed for reverse engineering APK files outputted source with mysterious resource IDs, as plain integers, which is not the most convenient way to read them. Therefore I started looking for any way to find some meaningful name from these ids. At the end of my development effort I found out, there is one file that usually might be used for that purpose – res/values/public.xml, as produced by apktool (if I remember correctly). However, according to its name it contains only public resources, so some of them are missing there (in my case at least some drawable type resources were missing). Therefore, I am publishing my program to do things even more reliably.

arscutils

This program requires my library created together, but which is separate project – libarsc. It is available, as usually through Github and also as a package to be downloaded from PyPI. Just type:

pip install libarsc

with proper privileges. Continue reading “How to convert Android resource ID back into its name” →

Posted in UncategorizedTagged Android, English, Python, Reverse EngineeringLeave a comment

LKV373A: state of the reverse engineering

Posted on January 14, 2018 - October 17, 2019 by Kamil (aka. v3l0c1r4pt0r)

This article is part of series about reverse-engineering LKV373A HDMI extender. Other parts are available at:

  • Part 1: Firmware image format
  • Part 2: Identifying processor architecture
  • Part 3: Reverse engineering instruction set architecture
  • Part 4: Crafting ELF
  • Part 5: Porting objdump
  • Part 6: State of the reverse engineering
  • Part 7: radare2 plugin for easier reverse engineering of OpenRISC 1000 (or1k)

Last time, I showed how to do objdump, able to disassemble instructions for not yet supported processor – LKV373A encoder. This time, as promised in part 5, I am just publishing, what I was able to do.

Reverse engineering repo

Repository is located, as usually, on Github, here. The most important file there is printout of encoder firmware, generated with my fork of objdump. Also, there are few scripts, I used to make process more automatic. Especially useful for someone, who might want to reproduce the process or continue my work might be the ELF generator script. It is written in Python and uses my ELF-creation library from part 4. As there is no way to install the library where it should be – /usr/lib/pythonX.X/site-packages, I used MAKEELFPATH environment variable to find makeelf.

Less important scripts, but still sometimes useful, are the ones to generate graph of function cross-references. They are able of generating .dot file, which can be converted to PNG (which is bad way of making it useful – it is 32768 pixels wide) or opened somewhere. And I used Gephi to read the final graph.

binutils development

Also binutils fork was improved a little bit. It is now possible to see symbols on every jump and call instruction. Moreover I did a kind of hack to be able to see references to data, as they mostly consisted of two instructions – first setting upper half of register, then adding lower half. So in that case, objdump is now displaying content of register, which most of the time don’t work, as objdump parses code linearly, without caring about jumps. But, if this opcode pair is used to really reference some address, it is quite reliable, so it is possible to see the address, as well as symbol name, in same way as with calls. Also, there is much more information about opcode types, so completely unknown instructions had been eliminated. Some of them were not used a single time and were renamed to resXX – for reserved.

Does it make sense?

Now, as I know really a lot about the firmware, it is time to try to answer the question in the heading. Well, the goal of reversing the encoder was to find compression and checksum algorithm for SMEDIA/ITE firmware blob. And, as far as I know now, it is really likely that at least compression algorithm is in fact somewhere here. I can say that, because I’ve seen routine for processing the data that seem to be compressed in SMEDIA/SMAZ container. Moreover, SMEDIA itself is also processed here, in original form, as one of the firmware’s responsibilities is firmware upgrade, so it is being copied to some internal ROM. So, if both – compressed and decompressed versions of firmware is here, then decompression also should be somewhere.

Now, this reverse engineering work might take really, really long time to get some results, but on the other hand, I might find, what I am looking for today. So, now the topic will probably seem to be dead for some undefined time.

Posted in Reversing LKV373ATagged English, Reverse EngineeringLeave a comment

LKV373A: porting objdump

Posted on December 30, 2017 - October 17, 2019 by Kamil (aka. v3l0c1r4pt0r)

This article is part of series about reverse-engineering LKV373A HDMI extender. Other parts are available at:

  • Part 1: Firmware image format
  • Part 2: Identifying processor architecture
  • Part 3: Reverse engineering instruction set architecture
  • Part 4: Crafting ELF
  • Part 5: Porting objdump
  • Part 6: State of the reverse engineering
  • Part 7: radare2 plugin for easier reverse engineering of OpenRISC 1000 (or1k)

After part number four, we already have ELF file, storing all the data we found in firmware image, described in a way that should make our analysis easier. Moreover, we have ability to define new symbols inside our ELF file. The next step is to add support for our custom architecture into objdump and this is what I want to show in this tutorial.

Finding best architecture to copy

If we want to set up new architecture in objdump code, we need to learn interfaces that need to be implemented. It would be easier if we can use some existing code to do so. After some looking into the binutils’ code I learned that what is of special interest are bfd and opcodes libraries. They contain code dedicated to particular architectures. The first one seem to be related to object file handling (which in our case is ELF), so we should not tinker with it too much. Second one is related to disassembling binary programs, so is what we are looking for.

I did some quick examination of source code related to popular architectures and it seems not to be easy to adjust to our needs. Architecture I found to be best suitable for modification is Microblaze. Its source seem to be quite well-written, clean and short. Also from my research of architecture name for LKV373A (part 2, failed by the way) I also remember it is quite similar to the one present in LKV373A, so it is even better decision to use it.

Compiling objdump for target architecture

At first it is useful to learn how to compile objdump, so it will be able to disassemble program written for our target. Microblaze is not really a mainstream architecture, so there aren’t many programs compiled for it available online after typing 'microblaze program elf' into usual search engine. However, I was able to find 2 of them, so I was able to verify that compilation worked. If you can’t find any, I uploaded these to MEGA, so they can serve as test cases. First one is minimal valid file, the other one is quite huge.

Compilation is very easy. The only thing that needs to be done beside usual ./configure && make && make install is adding target option to configure script. So, the script looks as follows:

./configure --target=microblaze-elf

Of course, install step can safely be skipped as well as compilation of other tools, beside objdump. objdump itself seem to be built using make binutils/objdump. However it can’t be build successfully using that shortcut, so whole binutils package must be configured the way, everything not buildable is excluded from the build.

Setting up own architecture

Next step is to add support for our brand new, custom architecture to binutils’ configuration files and copy microblaze sources, so they will simulate our architecture, until we will write our own implementation. Then it should be possible to test objdump again, against our sample microblaze programs and disassembly should still work.

Even without any modification to binutils’ source or configs, it should be possible to configure it for any random architecture. The only constraint is format of the target string: ARCH-OS-FORMAT, where FORMAT is most likely to be elf. So, if we pass lkv373a-unknown-elf as target, it will work. -unknown part is usually skipped and this will not work. If we need it to work, config.sub must be modified. config.sub is used to convert any string, passed to configure into canonical form, so in our case lkv373a-unknown-elf. If it detects, that it is already in canonical form, it does nothing.

Final configure command will be slightly more complex, as we have to disable some parts, that are not of our interest and requires additional effort to work:

./configure --target=lkv373a-unknown-elf --disable-gas --disable-ld --disable-gdb

Although passing something random as target option works on configure stage, it will obviously fail on make stage. What make is doing at first is configuring all the sublibraries. What is of our interest is bfd and opcodes. And the first one fails. So this is the first problem, we need to get rid of.

bfd/config.bfd

The purpose of this file is to set some environment variables depending on target architecture. If it does not know the architecture, it returns error to caller, which is probably bfd’s configure script, called by make. According to documentation in file header, it sets following variables:

  1. targ_defvec – default vector. This links target to list of objects that will provide support for ELF file built for specific architecture (stored in bfd/configure.ac)
  2. targ_selvecs – list of other selected vectors. Useful e.g. when we need support for both 32- and 64-bit ELFs. Not needed here.
  3. targ64_selvecs – 64-bit related stuff. Used when target can be both 32- and 64-bit, meaningless in our case.
  4. targ_archs – name of the symbol storing bfd_arch_info_type structure. It provides description of architecture to support.
  5. targ_cflags – looks like some hack to add extra CFLAGS to compiler. We don’t care.
  6. targ_underscore – not sure what it is, should have no impact on our goals (possible values are yes or no)

To sum up, what we need to do on this step is to define default vector, we will later add to configure.ac and set name of architecture description structure. The structure itself will be defined later. Finally, I ended up with the following patch:

@@ -173,6 +173,7 @@ hppa*)     targ_archs=bfd_hppa_arch ;;
 i[3-7]86)   targ_archs=bfd_i386_arch ;;
 i370)     targ_archs=bfd_i370_arch ;;
 ia16)     targ_archs=bfd_i386_arch ;;
+lkv373a)  targ_archs=bfd_lkv373a_arch ;;
 lm32)           targ_archs=bfd_lm32_arch ;;
 m6811*|m68hc11*) targ_archs="bfd_m68hc11_arch bfd_m68hc12_arch bfd_m9s12x_arch bfd_m9s12xg_arch" ;;
 m6812*|m68hc12*) targ_archs="bfd_m68hc12_arch bfd_m68hc11_arch bfd_m9s12x_arch bfd_m9s12xg_arch" ;;
@@ -924,6 +925,10 @@ case "${targ}" in
     targ_defvec=iq2000_elf32_vec
     ;;

+  lkv373a*-*)
+    targ_defvec=lkv373a_elf32_vec
+    ;;
+
   lm32-*-elf | lm32-*-rtems*)
     targ_defvec=lm32_elf32_vec
     targ_selvecs=lm32_elf32_fdpic_vec

bfd/configure.ac

Now we need to define vector, we just declared to use for lkv373a architecture.

505     k1om_elf64_fbsd_vec)         tb="$tb elf64-x86-64.lo elfxx-x86.lo elf-ifunc.lo elf-nacl.lo elf64.lo $elf"; target_size=64 ;;
506     lkv373a_elf32_vec)           tb="$tb elf32-lkv373a.lo elf32.lo $elf" ;;
507     l1om_elf64_vec)              tb="$tb elf64-x86-64.lo elfxx-x86.lo elf-ifunc.lo elf-nacl.lo elf64.lo $elf"; target_size=64 ;;

Unfortunately, as we did modifications to .ac script, we now need to rebuild our configure. From my experience, any tinkering with autohell, after solving one problem, creates 5 more. We need to get into bfd directory and reconfigure project:

cd bfd
autoreconf

Now, if it worked for you, you should definitely go, play some lottery 🙂 . For me it said that I need exactly same version of autoconf as used by binutils’ developers. Because autoconf is so great, probably what I will show now is completely useless for anyone, but hacks I needed to do are at first to add:

20 m4_define([_GCC_AUTOCONF_VERSION], [2.69])

to the beginning of configure.ac file. Then bfd/doc/Makefile.am contains removed cygnus option at the beginning, in AUTOMAKE_OPTIONS, so we need to remove it. After that doing automake --add-missing, as autoreconf suggests, and then again autoreconf should solve the problem. But, as I said, this will probably not work for you. I can only wish you good luck.

(if were following the steps, you might have noticed that autoconf complained about not being in version 2.64 and we overridden version from 2.69 to 2.69 and it worked 🙂 , don’t ask me, why, please!)

After this step, compilation should start (and obviously will fail miserably on bfd as it misses few symbols). Now its time to make bfd compilable.

bfd/elf32-lkv373a.c

This file is meant to provide support for custom features of ELF file. As we don’t have any, we can safely do nothing here. Good template of such file is elf32-m88k.c as it does exactly this.

One thing that seem to be important here is EM value of architecture described. EM is an enum used in ELF file to define target architecture, so it might be required to adjust in our new elf32-lkv373a.c file. By the way definition of this value have to be added to include/elf/common.h:

433 /* LKV373A architecture */
434 #define EM_LKV373A              0x373a

It might also be a good idea to add it to elfcpp/elfcpp.h. To make the file compile, it is necessary to add following to bfd/bfd-in2.h as value of bfd_architecture enum:

2398   bfd_arch_lkv373a,    /* LKV373A */

bfd/archures.c

As we declared bfd_lkv373a_arch as symbol with CPU description structure, we now need to add this declaration to archures.c, as this is the file, where it will be used. We have to add:

611 extern const bfd_arch_info_type bfd_l1om_arch;
612 extern const bfd_arch_info_type bfd_lkv373a_arch;
613 extern const bfd_arch_info_type bfd_lm32_arch;

bfd/targets.c

Similar situation is in targets.c file. Here we have to provide declaration of our vector as bfd_target. This will be another structure, which seem to be generated automatically, so we should not care about it.

704 extern const bfd_target l1om_elf64_fbsd_vec;
705 extern const bfd_target lkv373a_elf32_vec;
706 extern const bfd_target lm32_elf32_vec;

bfd/cpu-lkv373a.c

This last file, we need in bfd, provides bfd_arch_info_type structure and… that’s it! Can be easily borrowed from cpu-microblaze.c with only slight modifications. One thing that needs explanation here is section_align_power. As far as I understand it, it is power of two to which the beginning of the section in memory must be aligned. It should be safe to put 0 here, as we are not going to load our ELF into memory.

This should close the bfd part of initialization. As you can see, there was no development at all to be done here. Let’s now go to opcodes library.

opcodes/configure.ac

At first we need to define objects to build for LKV373A architecture in opcodes library. This is quite similar to what we had to do in configure.ac of bfd library.

282         bfd_iq2000_arch)        ta="$ta iq2000-asm.lo iq2000-desc.lo iq2000-dis.lo iq2000-ibld.lo iq2000-opc.lo" using_cgen=yes ;;
283         bfd_lkv373a_arch)       ta="$ta lkv373a-dis.lo" ;;
284         bfd_lm32_arch)          ta="$ta lm32-asm.lo lm32-desc.lo lm32-dis.lo lm32-ibld.lo lm32-opc.lo lm32-opinst.lo" using_cgen=yes ;;

Hopefully, -dis file will be enough to be implemented. I’ve made a copy from microblaze configuration. The same way we will copy whole source file and any related headers in the next step.

Now, similarly to bfd’s configure.ac, we have to reconfigure it. And again, nobody knows what errors we will encounter.

opcodes/disassemble.c

The only thing that have to be done here is to set pointer of disassemble function. For this following snippets should be added:

53 #define ARCH_lkv373a
255 #ifdef ARCH_lkv373a
256     case bfd_arch_lkv373a:
257       disassemble = print_insn_lkv373a;
258       break;
259 #endif

And to disassemble.h:

62 extern int print_insn_lkv373a           (bfd_vma, disassemble_info *);

opcodes/lkv373a-dis.c

This is, where real stuff will happen. As our goal, for now, is not to make implementation of LKV373A architecture, but rather set everything up, so objdump will build, we can copy source file from microblaze-dis.c. It is also required to copy headers, related to MicroBlaze, used by this file, so:

  • opcodes/microblaze-dis.h
  • opcodes/microblaze-opc.h
  • opcodes/microblaze-opcm.h

And change include directives in them to link to lkv373a file, rather than microblaze ones.

Now, optionally we could change names of any symbols referring to name microblaze, but this should not be required, as original microblaze files should not be included in the build. The only change than need to be done is print_insn_microblaze into print_insn_lkv373a, as this is what we added to disassemble.c.

You should now be able to compile working objdump with LKV373A support (of course with wrong implementation, for now). We can now verify that everything works on slightly modified ELF file for MicroBlaze architecture (EM field must point to LKV373A – value must be 0x373a). Well done!

NOTE: all the steps, done till now are available on tutorial-setup tag in repository on Github.

Functions to implement

Now, finally the real fun starts. Bindings between opcodes library and objdump itself, require at least print_insn_lkv373a to be implemented.

What should happen inside this function is quite simple and can be described in following steps:

  1. Gets bfd_vma and struct disassemble_info (called info below) as parameters
  2. Read raw data containing instructions using info->read_memory_func
  3. Call info->memory_error_func in case of any errors
  4. Use info->fprintf_func to print disassembled instruction into info->stream
  5. Optionally use info->symbol_at_address_func to determine if there is any symbol declared at address decoded from instructions
  6. If symbol exists, call info->print_address_func
  7. Return number of bytes consumed

Following is some documentation, I wrote for easier implementation (mostly translated inline comments), of functions to be called:

  /**
   * \brief Function used to get bytes to disassemble
   *
   * \param memaddr Address of the current instruction
   * \param myaddr Buffer, where the bytes will be stored
   * \param length Number of bytes to read
   * \param dinfo Pointer to info structure
   *
   * \return errno value or 0 for success
   */
  int (*read_memory_func)
    (bfd_vma memaddr, bfd_byte *myaddr, unsigned int length,
     struct disassemble_info *dinfo);
  /**
   * \brief Call if unrecoverable error occurred
   *
   * \param status errno from read_memory_func
   * \param memaddr Address of current instruction
   * \param dinfo Pointer to info structure
   */
  void (*memory_error_func)
    (int status, bfd_vma memaddr, struct disassemble_info *dinfo);
  /**
   * \brief Pointer to fprintf
   *
   * \param stream Pass info->stream here
   * \param char Format string
   * \param ... vargs
   *
   * \return Number of characters printed
   */
  typedef int (*fprintf_ftype) (void *, const char*, ...) ATTRIBUTE_FPTR_PRINTF_2;
  /**
   * \brief Determines if there is a symbol at the given ADDR
   *
   * \param addr Address to check
   * \param dinfo Pointer to info structure
   *
   * \return If there is returns 1, otherwise returns 0
   * \retval 1 If there is any symbol at ADDR
   * \retval 0 If there is no symbol at ADDR
   */
  int (* symbol_at_address_func)
    (bfd_vma addr, struct disassemble_info *dinfo);
  /**
   * \brief Print symbol name at ADDR
   *
   * \param addr Address at which symbol exists
   * \param dinfo Pointer to info structure
   */
  /* Function called to print ADDR.  */
  void (*print_address_func)
    (bfd_vma addr, struct disassemble_info *dinfo);

For easier start of development, this commit can be used as template. You can find effects of implementation according to this description on lkv373a branch of my binutils fork on Github. After this step, you should have working objdump, able to disassemble architecture of your choice.

Alternative way

According to binutils’ documentation, porting to new architectures should be done using different approach. Instead of copying sources from other architectures, developers should write CPU description files (cpu/ directory) and then use CGEN to generate all necessary files. However, I found these files way too complicated comparing to goal, I wanted to achieve, therefore I used the shortcut. In reality, however, this might be a better way, as the final result should be the support for new architecture not only in objdump, but also in e.g. GAS (GNU assembler). If you want to go that way, another useful resource might be description of CPU description language.

Plans for the future

As I am now able to speed up reverse engineering of both instruction set and LKV373A firmware, I am planning to create public repository of my progress and guess operations done by some more opcodes as I already know only few of them. So, I will probably push some more commits to binutils repo as well. I hope this will enable me to gain some more knowledge about LKV373A and allow, me or someone else, to reverse engineer second part of the firmware, which seem to be way more interesting that the one, I was reverse engineering till now.

Posted in Reversing LKV373A, TutorialsTagged English, hacking, hardware, Linux, programming, Reverse Engineering, softwareLeave a comment

LKV373A: crafting ELF

Posted on November 28, 2017 - October 17, 2019 by Kamil (aka. v3l0c1r4pt0r)

This article is part of series about reverse-engineering LKV373A HDMI extender. Other parts are available at:

  • Part 1: Firmware image format
  • Part 2: Identifying processor architecture
  • Part 3: Reverse engineering instruction set architecture
  • Part 4: Crafting ELF
  • Part 5: Porting objdump
  • Part 6: State of the reverse engineering
  • Part 7: radare2 plugin for easier reverse engineering of OpenRISC 1000 (or1k)

As we should now be able to follow any jump present in the code, it is now time to make analysis more automatic. My target tool for that purpose will be objdump. However, we still have firmware image as raw dump of memory. To be able to use objdump easily, we need to pack our firmware into some container understandable by objdump. Most obvious choice is ELF (Executable and Linkable Format) and this is what I am going to use.

For the purpose of packing data into ELF, I’ve made Python library that makes it easier. For now, it is able to split firmware image into sections, like .text or .data, so objdump will be able to disassembly only the parts of firmware that are in fact a code. Moreover, it can define symbols inside the binary, so it is possible to store information, where certain functions starts and ends, same for any variables, like strings. As of now, there is no CLI interface for the program. If it turns out that such interface is necessary (like for addition of many symbols), it will be added.

Library code can be downloaded from Github. Currently, any LKV373A-specific modifications to this library is stored on branch lkv373a, to not rubbish main – master branch. Throughout this tutorial, I assume, we are using code on this branch, so there might be some LKV373A-specifics, especially regarding enum types (i.e. processor architecture enum).

At this point, I need to warn, that I am not going to describe internal structure of ELF file, nor any features that might be visible from outside, like sections concept, so if you are not familiar with them, it is good time to learn about them, as it might be very difficult to understand, what I am writing about. There are many good resources explaining them. Ones I was using are: this blog post and this documentation.

Creating new ELF

Example code that creates brand new ELF file is as easy as:

 1 #!/usr/bin/python3
 2 # demo script for creating ELF
 3 import os
 4 from elf import *
 5 
 6 elf = ELF(e_machine=EM.EM_LKV373A)
 7 
 8 fp = os.open('lkv373a.fw.elf',os.O_CREAT|os.O_WRONLY)
 9 os.write(fp, bytes(elf))
10 os.close(fp)

This, at first does all necessary imports, then creates new ELF object in line 6, and, finally, converts it to bytes object and immediately writes to file descriptor. That’s it!

After this, you should get valid, empty ELF file for architecture called lkv373a, which, obviously does not exists and no other program know how to handle, but we are going to change that in future.

While creating ELF object, few things can be defined, in addition to architecture id. They are all described in documentation, I will mention near the end of this tutorial. You are also free to dig in structure of ELF object. There is no encapsulation in it and structure validation is very permissive, so even completely broken ELFs could be produced, if needed.

Adding section

Next step is to add some sections to our ELF file.

fw = os.open('LKV373A_TX_V3.0c_d_20161116_bin.bin',os.O_RDONLY)
fw_blob = os.read(fw, 0xffffffff)

irq_blob = fw_blob[:0x1000]
text_blob = fw_blob[0x7d100:0x7d100+0x0b53c0]
data_blob = fw_blob[0x0b53c0:0x0b53c0+0x102060]
smedia_blob = fw_blob[0x200000:0x200000+0x283105]

irq_id = elf.append_section('.irq',irq_blob,0)
txt_id = elf.append_section('.text',text_blob,0x7d100)
data_id = elf.append_section('.data',data_blob,0x0b53c0)
smedia_id = elf.append_section('.smedia',smedia_blob, 0x200000)

At first, I am extracting them from firmware image and then inserting them to ELF object. append_section is a handy wrapper to low-level modifications that must be done on ELF structure, hidden under what we can see as ELF instance (these low-level structures are, however still available to the user as ELF.Elf member).

Modifying section attributes

Ok, so now we have sections in our ELF file, ready to save to disk. Before that, one thing can yet be done: setting proper attributes. They tell readers, if program is able to write or execute sections of memory, among other features, I am going to ignore here. This might be useful, as some readers might be confused about what is code (text) and what is data. In our case, we have two text sections (.irq and .text), so we are going to set them executable flag (SHF_EXECINSTR). Furthermore, we will set SHF_ALLOC flag for any section that is going to be loaded into memory (so all of them).

This can be done with:

elf.Elf.Shdr_table[irq_id].sh_flags = SHF.SHF_ALLOC | SHF.SHF_EXECINSTR
elf.Elf.Shdr_table[txt_id].sh_flags = SHF.SHF_ALLOC | SHF.SHF_EXECINSTR
elf.Elf.Shdr_table[data_id].sh_flags = SHF.SHF_ALLOC
elf.Elf.Shdr_table[smedia_id].sh_flags = SHF.SHF_ALLOC

Adding segment

Segments are another concept, existing beside sections. They are stored in program header of ELF file and are somehow linked to section data. They allow to define another set of attributes to areas in memory. I don’t think they will be required to define, to perform analysis in objdump, but since at least one such program header, defining segment must exist in ELF file of type executable, there is interface similar to this for sections.

To define new segment, based on .text section, you can issue:

elf.append_segment(txt_id, flags='rx')

This also marks the segment as read and executable, but not writable.

Loading existing ELF

Loading existing ELF can be easily done from file with:

newelf, b = ELF.from_file('lkv373a.fw.elf')

Alternatively, it can also be loaded from bytes object:

fd = os.open('some.elf', os.O_RDONLY)
b = os.read(fd, 0xffff)
os.close(fd)
manualelf, b = Elf32.from_bytes(b)

In latter case, I assumed that os library is already imported into python.

Adding a symbol

This is very useful for making analysis of code. New symbol can be added using calls like:

elf.append_symbol('irq0', irq_id, 0, 0x44, STB.STB_GLOBAL, STT.STT_FUNC)
elf.append_symbol('sprintf', txt_id, 0x9b9f8-0x7d100, 0x78, STB.STB_GLOBAL,
        STT.STT_FUNC)
elf.append_symbol('thread_c_path', data_id, 0xba78a-0x0b53c0, 0xba7bb-0xba78a,
        STB.STB_LOCAL, STT.STT_OBJECT)

First call defines function of length 0x44 in .irq section. To do this, ID of .irq section must be known. Luckily, we want to add symbol at the beginning of the section, so as offset, 0 was provided.

In the second case, we also want to define a function, but now we only know absolute address of the function (0x9b9f8), but what we need to pass is offset in .text section. To achieve this, we need to subtract address of the start of .text section (0x7d100).

In the last example, we define a string as an object of certain address and length. Both address and length are computed by subtracting absolute addresses. This symbol will be marked as local, which is default behavior for append_symbol function.

Library documentation

There are many more things possible to do using makeelf library. What I showed here is mostly, what is possible using high-level wrappers, doing many things under the hood. But as there is also low-level interface, virtually anything is possible.

To make exploring interfaces easier, I’ve made doxygen documentation for most of the library. It can be found on my server, here. Feel free to use the library for anything you want.

Conclusion

The library presented here should allow us make one step further to easy to use reverse engineering environment. It will by the way allow to store new findings in easily-modifiable Python scripts.

What I showed in examples to library interfaces split LKV373A firmware image into 4 sections. At this moment I already know that there are at least 6 sections, where code and data are in two parts (forming ICDCDS layout, where I-irq, C-code and so on). Also there should be some more symbols possible to place at this moment.

If I succeed in porting objdump, or any other tool able to disassemble ELF file, next step would be to publish Python script, utilizing library presented here, that annotates LKV373A firmware. So stay tuned, I hope there will be many further interesting findings throughout this reversing process!

Posted in Reversing LKV373A, TutorialsTagged ELF, English, firmware, hacking, hardware, library, Python, Reverse EngineeringLeave a comment

Posts navigation

Older posts

Tags

Aero Android assembly C CAN can-hacking cmake Delphi Dreamspark electronics English FAT FAT32 FM Gingerbread GNU Radio GRC hacking hardware JavaCard JCOP kanał 14 kernel library Linux pinout PKI polski programming Python radio Reverse Engineering RTL-SDR SDC SDM SDR smart card software tor tty UART wifi Windows X.509 Xperia Pro

Recent Posts

  • Reading and programming 93Cx6 EEPROM with Digispark
  • Busybox-based Linux distro from scratch
  • Meet CC Factory – a factory for cross compilers
  • Peugeot 407 rain sensor pinout
  • OpenRISC 1000 support integrated into radare2

Recent Comments

  • Kamil (aka. v3l0c1r4pt0r) on Mounting encrypted Android emulator image
  • x on Mounting encrypted Android emulator image
  • Steve Quate on Playing with GF-07 GPS device
  • Joe on Security analysis of spy camera sold by Chinese suppliers: iMiniCam app
  • Robinson Dorion on Busybox-based Linux distro from scratch

Categories

  • News
  • Random
  • Reversing LKV373A
  • Setting up new v3 Hidden Service with ultimate security
  • Tutorials
  • Uncategorized
  • Understanding JCOP

Links

  • Me @ github
  • LKV373A Wiki
  • DevTomek

Archives

  • December 2020
  • November 2020
  • October 2020
  • August 2020
  • December 2019
  • November 2019
  • October 2019
  • August 2019
  • July 2019
  • February 2019
  • November 2018
  • October 2018
  • June 2018
  • May 2018
  • March 2018
  • February 2018
  • January 2018
  • December 2017
  • November 2017
  • September 2017

Meta

  • Log in
  • Entries feed
  • Comments feed
  • WordPress.org
Proudly powered by WordPress | Theme: micro, developed by DevriX.