Try   HackMD

Livepatch the process in userspace

If there is a problem when the process is running, we stop the process and observe the debugging log, and then update the code to try to reproduce the problem.

But when you stop this process, it means that the current environment may change.
So in this case livepatch can be used

LivePatch repo

Theory

When a program be loaded to memory, it will be loaded by elf format into the VMA. Loader will also link the dynamci lib to support it.

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More β†’

Use /proc/<PID>/maps to get the map

$ cat /proc/$(pidof testlive)/maps 
55869ea92000-55869ea93000 r--p 00000000 00:2d 281                        /home/roy/src-code/github/roy/00.project/livepatch/testlive
55869ea93000-55869ea94000 r-xp 00001000 00:2d 281                        /home/roy/src-code/github/roy/00.project/livepatch/testlive
55869ea94000-55869ea95000 r--p 00002000 00:2d 281                        /home/roy/src-code/github/roy/00.project/livepatch/testlive
55869ea95000-55869ea96000 r--p 00002000 00:2d 281                        /home/roy/src-code/github/roy/00.project/livepatch/testlive
55869ea96000-55869ea97000 rw-p 00003000 00:2d 281                        /home/roy/src-code/github/roy/00.project/livepatch/testlive
55869f60d000-55869f62e000 rw-p 00000000 00:00 0                          [heap]
7f5a33ea2000-7f5a33ea5000 rw-p 00000000 00:00 0 
7f5a33ea5000-7f5a33ecd000 r--p 00000000 08:01 3862                       /usr/lib/x86_64-linux-gnu/libc.so.6
7f5a33ecd000-7f5a34062000 r-xp 00028000 08:01 3862                       /usr/lib/x86_64-linux-gnu/libc.so.6
7f5a34062000-7f5a340ba000 r--p 001bd000 08:01 3862                       /usr/lib/x86_64-linux-gnu/libc.so.6
7f5a340ba000-7f5a340bb000 ---p 00215000 08:01 3862                       /usr/lib/x86_64-linux-gnu/libc.so.6
7f5a340bb000-7f5a340bf000 r--p 00215000 08:01 3862                       /usr/lib/x86_64-linux-gnu/libc.so.6
7f5a340bf000-7f5a340c1000 rw-p 00219000 08:01 3862                       /usr/lib/x86_64-linux-gnu/libc.so.6
7f5a340c1000-7f5a340ce000 rw-p 00000000 00:00 0 
7f5a340d3000-7f5a340d8000 rwxp 00000000 00:00 0 
7f5a340d8000-7f5a340da000 rw-p 00000000 00:00 0 
7f5a340da000-7f5a340dc000 r--p 00000000 08:01 3859                       /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7f5a340dc000-7f5a34106000 r-xp 00002000 08:01 3859                       /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7f5a34106000-7f5a34111000 r--p 0002c000 08:01 3859                       /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7f5a34112000-7f5a34114000 r--p 00037000 08:01 3859                       /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7f5a34114000-7f5a34116000 rw-p 00039000 08:01 3859                       /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
7ffff3c6f000-7ffff3c90000 rw-p 00000000 00:00 0                          [stack]
7ffff3d41000-7ffff3d45000 r--p 00000000 00:00 0                          [vvar]
7ffff3d45000-7ffff3d47000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall]
    

We can execute a process to hack it and load the fix function into the target process

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More β†’

Then use modify the target process. Let call bug_func be replaced by fix_func

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More β†’

How to work

As we know, the gdb can hack the runtime program. We can use the gdb to set paramater value, jump to the sepcific instruction. So how does the gdb make it? The answer is ptrace

So we can use the ptrace to control how the process executes. Like PTRACE_ATTACH to attach the process, PTRACE_PEEKDATA/PTRACE_POKEDATA to get and set data into the target process VMA.

Now, We have the method to control it, and we also need a library to help to get elf section. Bfd library is a good tool for us. Using this, we get the symbol table, the function address, and the most importart is getting .got/.got.plt/.rela.plt these section to help the fix_func to redirect the instruction in .plt section.

Q: Why do we need to redirect it ?
A: When we build the so file, this file only has the patch function, so the linker does not know "actual" address of the shared library in the target process. So the .plt section will be filled with "0". If we do not redirect it, the shared library be executed with the "0" insturction, this will make system fail.

executing

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More β†’

the target program is

#include <stdio.h>
#include <time.h>
#include <limits.h>
#include <unistd.h>
#include <sys/mman.h>

int func_J(int a, int b)
{
    char *str_P = "I'm wrong function...QQ";
    printf("in %s\n", str_P);
    sleep(3);
    printf("exit %s\n", str_P);
    return (a+b);
}


int main ()
{

    while(1) {
        int a = func_J(1, 2);
        sleep(3);
        printf("In main get calculating result: %d\n", a);
        if (12 == a) {
            printf("=== You fix it !!! (%d)\n ===", a);
            break;
        } else {
            printf("=== No, this is not the right answer....(%d) ===\n", a);
        }
    }

}

the patch file is

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stddef.h>
#include <dlfcn.h>

int func1(int a, int b) {
    printf("in fixup\n");    
    sleep(2);
    printf("exit fixup\n");
    return (a*10+b);
}

How to build it:

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More β†’

Ref

You can use readelf –relocs to get the relocation section

$ readelf --relocs libfoo.a

Relocation section '.rela.dyn' at offset 0x488 contains 7 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000003e10  000000000008 R_X86_64_RELATIVE                    1130
000000003e18  000000000008 R_X86_64_RELATIVE                    10f0
000000004028  000000000008 R_X86_64_RELATIVE                    4028
000000003fe0  000100000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_deregisterTM[...] + 0
000000003fe8  000300000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0
000000003ff0  000400000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_registerTMCl[...] + 0
000000003ff8  000600000006 R_X86_64_GLOB_DAT 0000000000000000 __cxa_finalize@GLIBC_2.2.5 + 0

Relocation section '.rela.plt' at offset 0x530 contains 2 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000004018  000200000007 R_X86_64_JUMP_SLO 0000000000000000 puts@GLIBC_2.2.5 + 0
000000004020  000500000007 R_X86_64_JUMP_SLO 0000000000000000 sleep@GLIBC_2.2.5 +     

for this example we need to relocate printf and sleep function to actual address.