Reverse Engineering the XignCode Anti-Cheat Library | XEM and XEL File Analysis

Overview

I recently downloaded and started playing the game Boxing Star. I decided to take a peek under the hood to checkout the game's internals. Within the application's lib directory, I found the armeabi-v7a shared-library libxigncode.so, which immediately peaked my interested. After dicking around in IDA and a few Google searches, it was pretty clear to me that this was probably an anti-cheat library. So here we are in another blog series where I pretend to know what I am doing.

XEM and XEL File Analysis

The java portion of the XignCode library is contained in the com.wellbia.xigncode package.

wellbia_package.png

The entry point into this library is the initializeXigncode() method.

.method protected initializeXigncode()I
          .registers 4
00000000  invoke-static       XigncodeClient->getInstance()XigncodeClient
00000006  move-result-object  v0
00000008  sget-object         v1, XigncodeActivity->mXigncodeLicense:String
0000000C  sget-object         v2, XigncodeActivity->mXigncodeParam:String
00000010  invoke-virtual      XigncodeClient->initialize(Activity, String, String, XigncodeClientSystem$Callback)I, v0, p0, v1, v2, p0
00000016  move-result         v0
00000018  if-eqz              v0, :1E
:1C
0000001C  return              v0
:1E
0000001E  const/4             v0, 0
00000020  goto                :1C
.end method

After a few subsequent calls, the library bridges into JNI through the XigncodeClientSystem.ZCWAVE.InitializeEx and XigncodeClientSystem.ZCWAVE.Initialize methods.

call_flow.png

After digging into the initialization functions, I noticed quite a bit calls to stat and fopen, so I became interested in the files being read during this stage. I wrote a basic Frida script to hook each of these functions and print the path to the target file. Some of the things that immediately caught my eye were the following.

/sdcard/Android/data/com.ftt.boxingstar.gl.aos/files/xigncode/xtmp.xem
/data/user/0/com.ftt.boxingstar.gl.aos/xigncode/ynina.xem
/data/user/0/com.ftt.boxingstar.gl.aos/xigncode/xnina.xem
/data/user/0/com.ftt.boxingstar.gl.aos/xigncode/xmag.xem
/data/user/0/com.ftt.boxingstar.gl.aos/xigncode/xmag.xem
/data/user/0/com.ftt.boxingstar.gl.aos/xsariel.xem
/sdcard/Android/data/com.ftt.boxingstar.gl.aos/files/xigncode/xtmp.xem
/data/user/0/com.ftt.boxingstar.gl.aos/xigncode/ynina.xem
/data/user/0/com.ftt.boxingstar.gl.aos/xigncode/ynina.xem
/data/user/0/com.ftt.boxingstar.gl.aos/xigncode/xmag.xem
/data/user/0/com.ftt.boxingstar.gl.aos/xigncode/ynina.xem
/data/user/0/com.ftt.boxingstar.gl.aos/xigncode/xmag.xem
/data/user/0/com.ftt.boxingstar.gl.aos/xigncode/xmag.xem
/data/user/0/com.ftt.boxingstar.gl.aos/xraphael.xem
/sdcard/Android/data/com.ftt.boxingstar.gl.aos/files/xigncode/xtmp.xem
/data/user/0/com.ftt.boxingstar.gl.aos/xigncode/xmag.xem

I pulled xraphael.xmem file from the application's data directory and found that it was actually an ELF binary.

╭─rotlogix@carcossa ~/Downloads
╰─$ file xraphael.xem
xraphael.xem: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /system/bin/linker, stripped

The library xraphael.xmem contained the following exports that looked mad interesting.

zcwave.png

I also pulled xsariel.xem and found that it was also an ELF binary.

╭─rotlogix@carcossa ~/Downloads
╰─$ file xsariel.xem
xsariel.xem: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /system/bin/linker, stripped

After throwing the library into IDA, it also had the same interesting exports. After checking the application's process mappings I saw that only the xraphael.xem library was actually mapped into memory.

maps.png

After digging around in the main library libxigncode.so, I found where the ZCWAVE_SendCommand was actually being referenced.

call_zcwave_send_command.png

When examining the cross-references to the function that contained the call to the ZCWAVE_SendCommand function, I noticed that the originating function was something I had notated earlier in my reverse engineering efforts.

cross_references_to_zwave_send_command.png

The ILLEGAL_PROGRAM_DETECTED function is called during the initialization phase of the main library. My assumption early on was that it was trying to perform some anti-debugging measures. However, once I was able to inject Frida into the process, I stopped caring about what it was attempting to do all together. Regardless, I now know that the ZCWAVE_SendCommand function is called during initialization. At this point I was really starting to think this was some sort of custom protocol.

We still have a few 'xem' libraries to checkout.

/data/data/com.ftt.boxingstar.gl.aos/xigncode # ls -la
total 24552
drwx------ 2 u0_a124 u0_a124    4096 2018-07-21 18:18 .
drwx------ 9 u0_a124 u0_a124    4096 2018-07-21 18:18 ..
-rw------- 1 u0_a124 u0_a124 8376320 2018-07-21 19:42 xmag.xem
-rw------- 1 u0_a124 u0_a124 8376320 2018-07-21 18:18 xnina.xem
-rw------- 1 u0_a124 u0_a124 8376320 2018-07-21 18:18 ynina.xem

After pulling and examining the xmag.xem file, it appeared to only contain data. The xnina.xem and ynina.xem also appeared to be the same.

$ file xmag.xem
xmag.xem: data
$ hexdump -n40 xmag.xem
0000000 00 00 00 00 7d a8 54 be b3 72 73 74 50 75 73 74
0000010 29 11 1d 15 7c 0d 16 19 53 75 73 74 54 75 73 74
0000020 55 75 73 74 4a 2a c5 74
0000028

When I opened up the xmag.xem file in HexFiend, there were a ton of strings that lead me to believe this was also a shared-library which was potentially packed in some way.

strings.png

The xel file I was able to pull from the SDCARD was also just data.

/sdcard/Android/data/com.ftt.boxingstar.gl.aos/files/xigncode # ls -la
total 2828
drwxrwx--x 2 u0_a124 sdcard_rw    4096 2018-07-21 18:18 .
drwxrwx--x 9 u0_a124 sdcard_rw    4096 2018-07-21 18:19 ..
-rw-rw---- 1 u0_a124 sdcard_rw 2880000 2018-07-21 20:25 xigncode.xel
-rw-rw---- 1 u0_a124 sdcard_rw       0 2018-07-21 19:42 xtmp.xem

Conclusion

At this point I've gathered the following information

  • *.xem files can either be ELF binaries or just pure data
  • *.xel files appear to just contain pure data
  • The ZCWAVE_SendCommand function is really interesting and is called from the main library during initilization
  • The anti-cheat library might be using a custom protocol for communication with the game server
  • Only one *.xem appears to mapped into memory once the application has finished booting

At this point I am probably going to head back into the libxigncode.so to investigate further. Initially when I decompiled the application, I was looking at all of the shared-libraries it included.

drwxr-xr-x  18 rotlogix  staff       576 Jul 21 20:51 .
drwxr-xr-x   4 rotlogix  staff       128 Jul 21 12:00 ..
-rw-r--r--   1 rotlogix  staff     40116 Jul 21 12:00 libAnalytics.so
-rw-r--r--   1 rotlogix  staff   1291436 Jul 21 12:00 libApp.so
-rw-r--r--   1 rotlogix  staff     54660 Jul 21 12:00 libMessaging.so
-rw-r--r--@  1 rotlogix  staff   8376320 Jul 21 12:00 libgabriel.so
-rw-r--r--   1 rotlogix  staff   2070484 Jul 21 12:00 libgpg.so
-rw-r--r--   1 rotlogix  staff     19404 Jul 21 12:00 libmain.so
-rw-r--r--   1 rotlogix  staff   3774904 Jul 21 12:00 libmono.so
-rw-r--r--@  1 rotlogix  staff       160 Jul 21 12:00 libpickle.so
-rw-r--r--   1 rotlogix  staff  18281824 Jul 21 12:00 libunity.so
-rw-r--r--   1 rotlogix  staff   1470520 Jul 21 12:00 libxigncode.so

The libpickle.so and libgabriel.so libraries were just data.

file libgabriel.so
libgabriel.so: data

This makes me think they might potentially be packed. When my Frida script was hooking fopen, I did notice they were being opened, but they never appeared in the game's processing mappings, so maybe they are not actually libraries.

~ BW