Skip to content
This repository has been archived by the owner on Jul 7, 2024. It is now read-only.

running libc properly #10

Open
152334H opened this issue Oct 21, 2020 · 2 comments
Open

running libc properly #10

152334H opened this issue Oct 21, 2020 · 2 comments
Labels
enhancement New feature or request

Comments

@152334H
Copy link
Owner

152334H commented Oct 21, 2020

As I outlined in a writeup:

So far I have tried

  • Using LD_PRELOAD, which in the correct order (ld-linux.so first) will run the binary without crashing, although other issues still surface
  • Running ./ld-linux.so, as outlined in the writeup. This has numerous side effects, including the actual binary getting allocated to an 0x7f.* page instead of the expected 0x5.* address
  • LD_LIBRARY_PATH, which is finicky enough that I have not investigated it throughly in the past

Additional suggestions from #9 (comment)_

There are several ways to resolve this issue:
1. Set up a ubuntu18-04 docker environment
2. Use patchelf to change the path of interpreter and and library path
3. (The ugly way but the way i used most frequently other than docker) use vim to edit the binary directly to change the interpreter to ./ld.so and libc to ./libcccc (it's ./libcccc because it has the same number of letters as libc.so.6)
4. Run the binary as LD_PRELOAD=./libc.so.6 ./ld.so <challenge>. But this method will treat the challenge as a library so you end up with a different memory layout from normal execution
@152334H 152334H added the enhancement New feature or request label Oct 21, 2020
@152334H
Copy link
Owner Author

152334H commented Oct 27, 2020

An analysis of libc simulation methods

Every method here is analysed with mapcheck.c:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(){
  int pid = getpid();
  char s[512];
  sprintf(s, "cat /proc/%d/maps", pid);
  system(s);
  printf("%p\n", printf);
}

And ultimately, a fully correct sample should look like:

557ab6fa4000-557ab6fa5000 r-xp 00000000 09:01 27263875                   /home/a/mapcheck.orig
557ab71a4000-557ab71a5000 r--p 00000000 09:01 27263875                   /home/a/mapcheck.orig
557ab71a5000-557ab71a6000 rw-p 00001000 09:01 27263875                   /home/a/mapcheck.orig
7f7d921de000-7f7d92203000 r--p 00000000 09:01 5244220                    /usr/lib/x86_64-linux-gnu/libc-2.31.so
7f7d92203000-7f7d9237b000 r-xp 00025000 09:01 5244220                    /usr/lib/x86_64-linux-gnu/libc-2.31.so
7f7d9237b000-7f7d923c5000 r--p 0019d000 09:01 5244220                    /usr/lib/x86_64-linux-gnu/libc-2.31.so
7f7d923c5000-7f7d923c6000 ---p 001e7000 09:01 5244220                    /usr/lib/x86_64-linux-gnu/libc-2.31.so
7f7d923c6000-7f7d923c9000 r--p 001e7000 09:01 5244220                    /usr/lib/x86_64-linux-gnu/libc-2.31.so
7f7d923c9000-7f7d923cc000 rw-p 001ea000 09:01 5244220                    /usr/lib/x86_64-linux-gnu/libc-2.31.so
7f7d923cc000-7f7d923d2000 rw-p 00000000 00:00 0
7f7d923dc000-7f7d923dd000 r--p 00000000 09:01 5244212                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7f7d923dd000-7f7d92400000 r-xp 00001000 09:01 5244212                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7f7d92400000-7f7d92408000 r--p 00024000 09:01 5244212                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7f7d92409000-7f7d9240a000 r--p 0002c000 09:01 5244212                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7f7d9240a000-7f7d9240b000 rw-p 0002d000 09:01 5244212                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7f7d9240b000-7f7d9240c000 rw-p 00000000 00:00 0
7ffffd143000-7ffffd164000 rw-p 00000000 00:00 0                          [stack]
7ffffd17c000-7ffffd17f000 r--p 00000000 00:00 0                          [vvar]
7ffffd17f000-7ffffd180000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall]
0x7f7d92242e10

./ld-linux.so --library-path

Benefits

  • Very easy to run, so long as libc-database is present
  • Works well with multiple libraries

Issues

  • Mappings are all at 0x7f.*. This is evidently wrong for the binary itself, which should always start at 0x5.*.
  • Address offsets are, on rare occasions, wrong. This was discovered during N1CTF 2020

Sample

7fbcc316b000-7fbcc3190000 r--p 00000000 09:01 27283362                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/libc.so.6
7fbcc3190000-7fbcc3308000 r-xp 00025000 09:01 27283362                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/libc.so.6
7fbcc3308000-7fbcc3352000 r--p 0019d000 09:01 27283362                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/libc.so.6
7fbcc3352000-7fbcc3353000 ---p 001e7000 09:01 27283362                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/libc.so.6
7fbcc3353000-7fbcc3356000 r--p 001e7000 09:01 27283362                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/libc.so.6
7fbcc3356000-7fbcc3359000 rw-p 001ea000 09:01 27283362                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/libc.so.6
7fbcc3359000-7fbcc335f000 rw-p 00000000 00:00 0
7fbcc335f000-7fbcc3360000 r-xp 00000000 09:01 27263875                   /home/a/mapcheck.orig
7fbcc3360000-7fbcc355f000 ---p 00001000 09:01 27263875                   /home/a/mapcheck.orig
7fbcc355f000-7fbcc3560000 r--p 00000000 09:01 27263875                   /home/a/mapcheck.orig
7fbcc3560000-7fbcc3561000 rw-p 00001000 09:01 27263875                   /home/a/mapcheck.orig
7fbcc3561000-7fbcc3562000 r--p 00000000 09:01 27283356                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/ld-linux-x86-64.so.2
7fbcc3562000-7fbcc3585000 r-xp 00001000 09:01 27283356                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/ld-linux-x86-64.so.2
7fbcc3585000-7fbcc358d000 r--p 00024000 09:01 27283356                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/ld-linux-x86-64.so.2
7fbcc358e000-7fbcc358f000 r--p 0002c000 09:01 27283356                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/ld-linux-x86-64.so.2
7fbcc358f000-7fbcc3590000 rw-p 0002d000 09:01 27283356                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/ld-linux-x86-64.so.2
7fbcc3590000-7fbcc3591000 rw-p 00000000 00:00 0
7ffd0bf6e000-7ffd0bf8f000 rw-p 00000000 00:00 0                          [stack]
7ffd0bff9000-7ffd0bffc000 r--p 00000000 00:00 0                          [vvar]
7ffd0bffc000-7ffd0bffd000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall]
0x7fbcc31cfe10

LD_PRELOAD="/path/to/ld-linux /path/to/libc"

Benefits

  • PIE addresses are correctly at 0x5.*, unlike ./ld-linux
  • libc-database is (technically) not needed for this, so long as both ld-linux & libc.so.6 are linked with the challenge

Issues

  • need to do extra programming if extra libraries on top of libc.so.6 are used (alternatively, use LD_PRELOAD & LD_LIBRARY_PATH simultaneously)
  • mapping is still wrong --- ld-2.31.so is included twice, plus (discovered outside of this example) heap addresses are put after the first ld-2.31.so.
  • untested on the breaking N1CTF example

Sample

558660142000-558660143000 r-xp 00000000 09:01 27263875                   /home/a/mapcheck.orig
558660342000-558660343000 r--p 00000000 09:01 27263875                   /home/a/mapcheck.orig
558660343000-558660344000 rw-p 00001000 09:01 27263875                   /home/a/mapcheck.orig
7f647cb8c000-7f647cb8f000 rw-p 00000000 00:00 0
7f647cb8f000-7f647cbb4000 r--p 00000000 09:01 27283362                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/libc.so.6
7f647cbb4000-7f647cd2c000 r-xp 00025000 09:01 27283362                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/libc.so.6
7f647cd2c000-7f647cd76000 r--p 0019d000 09:01 27283362                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/libc.so.6
7f647cd76000-7f647cd77000 ---p 001e7000 09:01 27283362                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/libc.so.6
7f647cd77000-7f647cd7a000 r--p 001e7000 09:01 27283362                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/libc.so.6
7f647cd7a000-7f647cd7d000 rw-p 001ea000 09:01 27283362                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/libc.so.6
7f647cd7d000-7f647cd81000 rw-p 00000000 00:00 0
7f647cd81000-7f647cd82000 r--p 00000000 09:01 27283355                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/ld-2.31.so
7f647cd82000-7f647cda5000 r-xp 00001000 09:01 27283355                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/ld-2.31.so
7f647cda5000-7f647cdad000 r--p 00024000 09:01 27283355                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/ld-2.31.so
7f647cdad000-7f647cdae000 ---p 0002c000 09:01 27283355                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/ld-2.31.so
7f647cdae000-7f647cdaf000 r--p 0002c000 09:01 27283355                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/ld-2.31.so
7f647cdaf000-7f647cdb0000 rw-p 0002d000 09:01 27283355                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/ld-2.31.so
7f647cdb0000-7f647cdb3000 rw-p 00000000 00:00 0
7f647cdb3000-7f647cdb4000 r--p 00000000 09:01 5244212                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7f647cdb4000-7f647cdd7000 r-xp 00001000 09:01 5244212                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7f647cdd7000-7f647cddf000 r--p 00024000 09:01 5244212                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7f647cde0000-7f647cde1000 r--p 0002c000 09:01 5244212                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7f647cde1000-7f647cde2000 rw-p 0002d000 09:01 5244212                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7f647cde2000-7f647cde3000 rw-p 00000000 00:00 0
7ffc3e895000-7ffc3e8b6000 rw-p 00000000 00:00 0                          [stack]
7ffc3e90e000-7ffc3e911000 r--p 00000000 00:00 0                          [vvar]
7ffc3e911000-7ffc3e912000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall]
0x7f647cbf3e10

patchelf --set-interpreter $ld --replace-needed libc.so.6 $libc ./binary

Benefits

  • Closest mapping to the original
  • libc-database also technically unecessary

Issues

  • Requires modification of the binary itself
  • Untested on N1CTF example
  • Requires patchelf

Sample

55fe4bbc8000-55fe4bbc9000 r-xp 00000000 09:01 27263874                   /home/a/mapcheck.out
55fe4bdc8000-55fe4bdc9000 r--p 00000000 09:01 27263874                   /home/a/mapcheck.out
55fe4bdc9000-55fe4bdca000 rw-p 00001000 09:01 27263874                   /home/a/mapcheck.out
55fe4bdca000-55fe4bdcb000 rw-p 00003000 09:01 27263874                   /home/a/mapcheck.out
7f34f3bad000-7f34f3baf000 rw-p 00000000 00:00 0
7f34f3baf000-7f34f3bd4000 r--p 00000000 09:01 27283362                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/libc.so.6
7f34f3bd4000-7f34f3d4c000 r-xp 00025000 09:01 27283362                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/libc.so.6
7f34f3d4c000-7f34f3d96000 r--p 0019d000 09:01 27283362                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/libc.so.6
7f34f3d96000-7f34f3d97000 ---p 001e7000 09:01 27283362                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/libc.so.6
7f34f3d97000-7f34f3d9a000 r--p 001e7000 09:01 27283362                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/libc.so.6
7f34f3d9a000-7f34f3d9d000 rw-p 001ea000 09:01 27283362                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/libc.so.6
7f34f3d9d000-7f34f3da3000 rw-p 00000000 00:00 0
7f34f3da3000-7f34f3da4000 r--p 00000000 09:01 27283355                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/ld-2.31.so
7f34f3da4000-7f34f3dc7000 r-xp 00001000 09:01 27283355                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/ld-2.31.so
7f34f3dc7000-7f34f3dcf000 r--p 00024000 09:01 27283355                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/ld-2.31.so
7f34f3dd0000-7f34f3dd1000 r--p 0002c000 09:01 27283355                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/ld-2.31.so
7f34f3dd1000-7f34f3dd2000 rw-p 0002d000 09:01 27283355                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/ld-2.31.so
7f34f3dd2000-7f34f3dd3000 rw-p 00000000 00:00 0
7ffcbdcf2000-7ffcbdd13000 rw-p 00000000 00:00 0                          [stack]
7ffcbdd44000-7ffcbdd47000 r--p 00000000 00:00 0                          [vvar]
7ffcbdd47000-7ffcbdd48000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall]
0x7f34f3c13e10

@152334H
Copy link
Owner Author

152334H commented Oct 27, 2020

Test two: easyWrite clone (tcache_perthread_struct writing)

Because I have a machine available with libc6_2.31-0ubuntu9.1_amd64, all these tests are done on that version of libc.

Every method here is analysed with tcache.c:

#include <stdlib.h>
#define MALLOC_OFF 0x9d260
#define TCACHE_OFF 0x7ffff7fc04f0-0x7ffff7dcd000
#define F_HOOK_OFF 0x1eeb28
#define TCACHE_MAX_BINS 0x40

typedef struct tcache_struct {
      short counts[TCACHE_MAX_BINS];
      void *entries[TCACHE_MAX_BINS];
} tcache_struct;
void win(){ puts("success"); }
int main(){
    malloc(1);
    tcache_struct constructed_tcache = (tcache_struct) { .counts = {0, 0, 1}, .entries = {0,0, malloc-MALLOC_OFF+F_HOOK_OFF}};
    tcache_struct **tcache = malloc-MALLOC_OFF+TCACHE_OFF;
    *tcache = &constructed_tcache;
    puts("fake tcache in place");
    void *p = malloc(0x30);
    puts("overwriting free_hook");
    *(long long*)p = win;
    free(p);
}

And ultimately, a fully correct sample should look like:

fake tcache in place
overwriting free_hook
success

./ld-linux.so --library-path

fake tcache in place
overwriting free_hook

The program just ends. This matches up with what I experienced in N1CTF.

LD_PRELOAD="/path/to/ld-linux /path/to/libc"

Segmentation fault

This method terminates immediately when trying to deference **tcache. This happens because of the difference between the expected memory allocation:

7f7d923c9000-7f7d923cc000 rw-p 001ea000 09:01 5244220                    /usr/lib/x86_64-linux-gnu/libc-2.31.so
7f7d923cc000-7f7d923d2000 rw-p 00000000 00:00 0
7f7d923dc000-7f7d923dd000 r--p 00000000 09:01 5244212                    /usr/lib/x86_64-linux-gnu/ld-2.31.so

And the actual memory allocation:

7f647cd7a000-7f647cd7d000 rw-p 001ea000 09:01 27283362                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/libc.so.6
7f647cd7d000-7f647cd81000 rw-p 00000000 00:00 0
7f647cd81000-7f647cd82000 r--p 00000000 09:01 27283355                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/ld-2.31.so

For the latter, the page allocated for the unlabelled .tls map is contiguous (!) with that of ld-linux, whereas in the expected behavior, it isn't.

patchelf --set-interpreter $ld --replace-needed libc.so.6 $libc ./binary

fake tcache in place
overwriting free_hook

Like the ./ld-linux.so method, the program just ends.

7f34f3d9a000-7f34f3d9d000 rw-p 001ea000 09:01 27283362                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/libc.so.6
7f34f3d9d000-7f34f3da3000 rw-p 00000000 00:00 0
7f34f3da3000-7f34f3da4000 r--p 00000000 09:01 27283355                   /home/a/libc-database/libs/libc6_2.31-0ubuntu9.1_amd64/ld-2.31.so

The second line here matches with the expected allocation, but because ld-2.31.so is still contiguous, the write fails to affect the tcache.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant