본문 바로가기

Programming

Location of Stack Canary in x64 Linux Process

64비트 리눅스에서 스택카나리는 %FS:0x28 에서부터 가져오며, 이를 스택에 저장하고 함수가 끝나기전에 다시 %FS:0x28 과 비교한다. 그렇다면 %FS:0x28 은 정확히 어디에 있는것인가?? GDT 를 덤프떠서 %FS 의 base 를 얻기는 너무 어렵고 귀찮다. 


그래서 프로세스 풀메모리 스캐닝을 하는 GDB 스크립트를 하나 만들어서 아래와 같이 테스트 해보았다.

다음과 같이 간단한 카나리가 있는 static linked x64 바이너리를 가지고 실험을 해보자.


(gdb) shell cat a.c

#include <stdio.h>

int main(){

char buf[8];

printf("asdf\n");

return 0;

}


GDB 상에서 조사한 카나리는 아래와 같다.


0x127466d230bc8200


자, 이걸 전체 메모리스캐닝을해서 찾아보자.


(gdb) mem_scan $z

Pattern not found.

Pattern not found.

0x6c78a9

1 pattern found.

Pattern not found.

0x7fffffffe1e9

0x7fffffffe291

0x7fffffffe57a

3 patterns found.

Pattern not found.


4개의 값이 검출되었다.


힙에 하나..

(gdb) x/20wx 0x6c78a0

0x6c78a0: 0x00000000 0x00000000 0x30bc8200 0x127466d2

0x6c78b0: 0x00000000 0x00000000 0x00000000 0x00000000

0x6c78c0: 0x00000000 0x00000000 0x00000000 0x00000000

0x6c78d0: 0x00000000 0x00000000 0x00000000 0x00000000

0x6c78e0: 0x00000000 0x00000000 0x00000000 0x00000000


스택에 3개... 이중하나는 저장된 값이니 당연히 있는값이고

결국 FS:0x28 에 저장된 다른 사본의 후보는 힙에 1개, 스택에 2개가 있다.

(gdb) x/10wx 0x7fffffffe1e0

0x7fffffffe1e0: 0x00401a40 0x00000000 0x30bc8200 0x127466d2

0x7fffffffe1f0: 0x00000000 0x00000000 0x00401334 0x00000000

0x7fffffffe200: 0x00000000 0x00000000

(gdb) x/10wx 0x7fffffffe290

0x7fffffffe290: 0x30bc8200 0x127466d2 0x00000000 0x00000000

0x7fffffffe2a0: 0x00000000 0x00000000 0x00000000 0x00000000

0x7fffffffe2b0: 0x00000000 0x00000000

(gdb) x/10wx 0x7fffffffe570

0x7fffffffe570: 0x00000000 0x00000000 0xbc82a000 0x7466d230

0x7fffffffe580: 0xfaeca712 0x8f0cf2b2 0x36387886 0x0034365f

0x7fffffffe590: 0x00000000 0x762f0000

(gdb) i r $rsp

rsp            0x7fffffffe1e0 0x7fffffffe1e0


일단 힙에 있는 값을 변조시켜보자.

(gdb) set *0x6c78ac=0x41414141

(gdb) x/20wx 0x6c78a0

0x6c78a0: 0x00000000 0x00000000 0x30bc8200 0x41414141

0x6c78b0: 0x00000000 0x00000000 0x00000000 0x00000000

0x6c78c0: 0x00000000 0x00000000 0x00000000 0x00000000

0x6c78d0: 0x00000000 0x00000000 0x00000000 0x00000000

0x6c78e0: 0x00000000 0x00000000 0x00000000 0x00000000

(gdb) c

Continuing.

asdf

*** stack smashing detected ***: /var/www/a terminated

======= Backtrace: =========

[0x418ec5]

[0x418e8e]

[0x40119e]

[0x401334]

[0x401081]

======= Memory map: ========

00400000-004c2000 r-xp 00000000 08:01 1186663                            /var/www/a

006c1000-006c4000 rw-p 000c1000 08:01 1186663                            /var/www/a

006c4000-006ea000 rw-p 00000000 00:00 0                                  [heap]

7ffff7ffc000-7ffff7ffe000 rw-p 00000000 00:00 0 

7ffff7ffe000-7ffff7fff000 r-xp 00000000 00:00 0                          [vdso]

7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0                          [stack]

ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]


Program received signal SIGABRT, Aborted.

0x0000000000462dc5 in raise ()

(gdb) 


오호라... 힙에 저장된것이 비교대상의 원본이었다.

그렇다는것은 FS base 는 아래와 같다는뜻...

각각 필드가 무슨의미일까?


(gdb) x/30wx 0x6C7880

0x6c7880: 0x006c7880 0x00000000 0x006c3770 0x00000000

0x6c7890: 0x006c7880 0x00000000 0x00000000 0x00000000

0x6c78a0: 0x00000000 0x00000000 0x16128a00 0x7f2e1d08

0x6c78b0: 0x00000000 0x00000000 0x00000000 0x00000000

0x6c78c0: 0x00000000 0x00000000 0x00000000 0x00000000

0x6c78d0: 0x00000000 0x00000000 0x00000000 0x00000000

0x6c78e0: 0x00000000 0x00000000 0x00000000 0x00000000

0x6c78f0: 0x00000000 0x00000000

(gdb) 


나머지 포인터들은 자기자신을 가리키고있을뿐이고, 눈에띄는건 6c3770...


(gdb) x/30wx 0x6c3770

0x6c3770 <static_dtv+16>: 0x00000000 0x00000000 0x00000000 0x00000000

0x6c3780 <static_dtv+32>: 0x006c7820 0x00000000 0x00000001 0x00000000

0x6c3790 <static_dtv+48>: 0x00000000 0x00000000 0x00000000 0x00000000

0x6c37a0 <static_dtv+64>: 0x00000000 0x00000000 0x00000000 0x00000000

0x6c37b0 <static_dtv+80>: 0x00000000 0x00000000 0x00000000 0x00000000

0x6c37c0 <static_dtv+96>: 0x00000000 0x00000000 0x00000000 0x00000000

0x6c37d0 <static_dtv+112>: 0x00000000 0x00000000 0x00000000 0x00000000

0x6c37e0 <static_dtv+128>: 0x00000000 0x00000000

(gdb) 


뭐지이게?? 구글링해보자.


Initialization code for TLS in statically linked application ...

https://stuff.mit.edu/afs/sipb/project/gcc-3.2/OldFiles/...2.../libc-tls.c

static dtv_t static_dtv[3]; static struct { struct dtv_slotinfo_list si; /* The dtv_slotinfo_list data structure does not include the actual informatin since it is defined as an ...


즉 static 링킹된 바이너리에서의 TLS(thread Local Storage) 관련 자료구조다.

윈도우자와 마찬가지로 TLS 자료구조 속에 카나리 원본을 보관하고 있다.

그런데 어차피 ASLR 걸려있으면 이부분의 주소를 런타임이 아닌이상 알 수는 없으므로

안전하겠지만 만약 메모리릭으로 이 위치를 알고난뒤에 원하는데로 덮어쓰기까지 할수있다면

ASCII Armoring 의 상황에서도 카나리 우회가 가능해지는 일이 벌어지겠군 -_- ㅋㅋ


혹시모르니 스택에 있는 카나리들도 조작하고 어떻게되는지 보자.


(gdb) x/20wx 0x7fffffffe291

0x7fffffffe291: 0x0816128a 0x007f2e1d 0x00000000 0x00000000

0x7fffffffe2a1: 0x00000000 0x00000000 0x00000000 0x00000000

0x7fffffffe2b1: 0x00000000 0x00000000 0x00000000 0x00000000

0x7fffffffe2c1: 0x00000000 0x81000000 0x00004010 0xd8000000

0x7fffffffe2d1: 0xffffffe2 0x0000007f 0x00000000 0x01000000

(gdb) set *0x7fffffffe291=0x41414141

(gdb) x/10wx 0x7fffffffe57a

0x7fffffffe57a: 0x0816128a 0x137f2e1d 0xf523cb1c 0x783771cd

0x7fffffffe58a: 0x365f3638 0x00000034 0x00000000 0x7261762f

0x7fffffffe59a: 0x7777772f 0x5300612f

(gdb) set *0x7fffffffe57a=0x41414141

(gdb) c

Continuing.

asdf

[Inferior 1 (process 2176) exited normally]

(gdb) 


역시 아무일없다..?  그게 아니라


entry point 에서부터 브포걸고 확인해보면. 이상태에서 이미 스택에 canary 의 초기값이 들어가있고

__libc_start_main 에서 이 스택에 있는 값을 가져다가 하위 1바이트 마스킹해서 쓴것이었음...


(gdb) x/10gx 0x7fffffffe329

0x7fffffffe329: 0x23f76c019b2b325c 0x65648d3fbac9c919

0x7fffffffe339: 0x000034365f363878 0x0000000000000000

0x7fffffffe349: 0x2f706d742f000000 0x54565f4744580061

0x7fffffffe359: 0x48535300373d524e 0x505f544e4547415f

0x7fffffffe369: 0x00393038323d4449 0x535345535f474458


(gdb) disass main

Dump of assembler code for function main:

   0x000000000040105e <+0>: push   %rbp

   0x000000000040105f <+1>: mov    %rsp,%rbp

   0x0000000000401062 <+4>: sub    $0x70,%rsp

   0x0000000000401066 <+8>: mov    %fs:0x28,%rax

   0x000000000040106f <+17>: mov    %rax,-0x8(%rbp)

   0x0000000000401073 <+21>: xor    %eax,%eax

   0x0000000000401075 <+23>: movb   $0x1,-0x70(%rbp)

   0x0000000000401079 <+27>: mov    -0x8(%rbp),%rax

   0x000000000040107d <+31>: xor    %fs:0x28,%rax

   0x0000000000401086 <+40>: je     0x40108d <main+47>

   0x0000000000401088 <+42>: callq  0x437060 <__stack_chk_fail>

   0x000000000040108d <+47>: leaveq 

   0x000000000040108e <+48>: retq   

End of assembler dump.

(gdb) b *main+17

Breakpoint 2 at 0x40106f

(gdb) c

Continuing.


Breakpoint 2, 0x000000000040106f in main ()

(gdb) i r $rax

rax            0x23f76c019b2b3200 2591658864729076224

(gdb) 



이게 entry point 에서 메인가기전에 __libc_start_main 이 세팅해줌


   0x000000000040117e <+238>: mov    0x2bddfb(%rip),%rax        # 0x6bef80 <_dl_random>

   0x0000000000401185 <+245>: test   %rax,%rax

   0x0000000000401188 <+248>: je     0x401321 <__libc_start_main+657>

   0x000000000040118e <+254>: mov    (%rax),%rdx

   0x0000000000401191 <+257>: mov    %rdx,%rsi

   0x0000000000401194 <+260>: mov    %rdx,0x20(%rsp)

   0x0000000000401199 <+265>: and    $0x0,%sil

   0x000000000040119d <+269>: mov    %rsi,%fs:0x28


여기서 _dl_random 이 스택에 박힌 카나리값을 가리키는 포인터임...

그러면 이 스택에 있는 값이 원본인건데사실상... 이건 커널이 세팅해준듯함.




아무튼 이제 Dynamic Linking 된 64비트 ELF 에서는 어떻게 되는지 확인해보자.



(gdb) i r $rax

rax            0x8e58ce56dac8f700 -8189569049940134144

(gdb) ni



0x000000000040057b in main ()

(gdb) set $z="\xf7\xc8\xda"

(gdb) set $z[3]=0x56

(gdb) mem_scan $z

Pattern not found.

Pattern not found.

Pattern not found.

Pattern not found.

warning: Unable to access target memory at 0x7ffff7bd2e83, halting search.

Pattern not found.

Pattern not found.

Pattern not found.

Pattern not found.

Pattern not found.

0x7ffff7fe3729

1 pattern found.

Pattern not found.

Pattern not found.

Pattern not found.

Pattern not found.

0x7fffffffe1f9

0x7fffffffe57a

2 patterns found.

Pattern not found.

(gdb) 



흠... 비슷하게 나오는듯하다. 


0x7ffff7fe3729


이부분에 원본이 있는데


(gdb) shell cat /proc/2240/maps

00400000-00401000 r-xp 00000000 08:01 1186663                            /var/www/a

00600000-00601000 r--p 00000000 08:01 1186663                            /var/www/a

00601000-00602000 rw-p 00001000 08:01 1186663                            /var/www/a

7ffff7a1a000-7ffff7bcf000 r-xp 00000000 08:01 132002                     /lib/x86_64-linux-gnu/libc-2.15.so

7ffff7bcf000-7ffff7dcf000 ---p 001b5000 08:01 132002                     /lib/x86_64-linux-gnu/libc-2.15.so

7ffff7dcf000-7ffff7dd3000 r--p 001b5000 08:01 132002                     /lib/x86_64-linux-gnu/libc-2.15.so

7ffff7dd3000-7ffff7dd5000 rw-p 001b9000 08:01 132002                     /lib/x86_64-linux-gnu/libc-2.15.so

7ffff7dd5000-7ffff7dda000 rw-p 00000000 00:00 0 

7ffff7dda000-7ffff7dfc000 r-xp 00000000 08:01 134927                     /lib/x86_64-linux-gnu/ld-2.15.so

7ffff7fe2000-7ffff7fe5000 rw-p 00000000 00:00 0 

7ffff7ff9000-7ffff7ffb000 rw-p 00000000 00:00 0 

7ffff7ffb000-7ffff7ffc000 r-xp 00000000 00:00 0                          [vdso]

7ffff7ffc000-7ffff7ffd000 r--p 00022000 08:01 134927                     /lib/x86_64-linux-gnu/ld-2.15.so

7ffff7ffd000-7ffff7fff000 rw-p 00023000 08:01 134927                     /lib/x86_64-linux-gnu/ld-2.15.so

7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0                          [stack]

ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

(gdb) 


뭔가 이름없는 RW 매핑영역이다...


(gdb) x/10wx 0x7ffff7fe3720

0x7ffff7fe3720: 0x00000000 0x00000000 0xdac8f700 0x8e58ce56

0x7ffff7fe3730: 0x22eb1cea 0x641af660 0x00000000 0x00000000

0x7ffff7fe3740: 0x00000000 0x00000000

(gdb) set *0x7ffff7fe3729=0x41414141

(gdb) c

Continuing.

asdf

*** stack smashing detected ***: /var/www/a terminated

======= Backtrace: =========

/lib/x86_64-linux-gnu/libc.so.6(__fortify_fail+0x37)[0x7ffff7b24f47]

/lib/x86_64-linux-gnu/libc.so.6(__fortify_fail+0x0)[0x7ffff7b24f10]

/var/www/a[0x40059e]

/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7ffff7a3b76d]

/var/www/a[0x4004a9]

======= Memory map: ========

00400000-00401000 r-xp 00000000 08:01 1186663                            /var/www/a

00600000-00601000 r--p 00000000 08:01 1186663                            /var/www/a

00601000-00602000 rw-p 00001000 08:01 1186663                            /var/www/a

00602000-00623000 rw-p 00000000 00:00 0                                  [heap]

7ffff7804000-7ffff7819000 r-xp 00000000 08:01 134737                     /lib/x86_64-linux-gnu/libgcc_s.so.1

7ffff7819000-7ffff7a18000 ---p 00015000 08:01 134737                     /lib/x86_64-linux-gnu/libgcc_s.so.1

7ffff7a18000-7ffff7a19000 r--p 00014000 08:01 134737                     /lib/x86_64-linux-gnu/libgcc_s.so.1

7ffff7a19000-7ffff7a1a000 rw-p 00015000 08:01 134737                     /lib/x86_64-linux-gnu/libgcc_s.so.1

7ffff7a1a000-7ffff7bcf000 r-xp 00000000 08:01 132002                     /lib/x86_64-linux-gnu/libc-2.15.so

7ffff7bcf000-7ffff7dcf000 ---p 001b5000 08:01 132002                     /lib/x86_64-linux-gnu/libc-2.15.so

7ffff7dcf000-7ffff7dd3000 r--p 001b5000 08:01 132002                     /lib/x86_64-linux-gnu/libc-2.15.so

7ffff7dd3000-7ffff7dd5000 rw-p 001b9000 08:01 132002                     /lib/x86_64-linux-gnu/libc-2.15.so

7ffff7dd5000-7ffff7dda000 rw-p 00000000 00:00 0 

7ffff7dda000-7ffff7dfc000 r-xp 00000000 08:01 134927                     /lib/x86_64-linux-gnu/ld-2.15.so

7ffff7fe2000-7ffff7fe5000 rw-p 00000000 00:00 0 

7ffff7ff7000-7ffff7ffb000 rw-p 00000000 00:00 0 

7ffff7ffb000-7ffff7ffc000 r-xp 00000000 00:00 0                          [vdso]

7ffff7ffc000-7ffff7ffd000 r--p 00022000 08:01 134927                     /lib/x86_64-linux-gnu/ld-2.15.so

7ffff7ffd000-7ffff7fff000 rw-p 00023000 08:01 134927                     /lib/x86_64-linux-gnu/ld-2.15.so

7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0                          [stack]

ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]


Program received signal SIGABRT, Aborted.

0x00007ffff7a50425 in raise () from /lib/x86_64-linux-gnu/libc.so.6

(gdb) 



조작하면 역시나 SSP 에 걸린다. 결론은 뭐 비슷하다.

그렇다면 메모리 leak 이 가능할때 이 주소를 언제나 알아내는게 가능할까??


(gdb) x/100wx 0x7FFFF7FE3700

0x7ffff7fe3700: 0xf7fe3700 0x00007fff 0xf7fe2010 0x00007fff

0x7ffff7fe3710: 0xf7fe3700 0x00007fff 0x00000000 0x00000000

0x7ffff7fe3720: 0x00000000 0x00000000 0x41414100 0x8e58ce41

0x7ffff7fe3730: 0x22eb1cea 0x641af660 0x00000000 0x00000000

0x7ffff7fe3740: 0x00000000 0x00000000 0x00000000 0x00000000


이 부분의 주소를 다시 메모리스캐닝 해보자.


(gdb) set $q="\x37\xfe"

(gdb) set $q[2]=0xf7

(gdb) mem_scan $q

Pattern not found.

Pattern not found.

Pattern not found.

Pattern not found.

warning: Unable to access target memory at 0x7ffff7bd2e82, halting search.

Pattern not found.

Pattern not found.

Pattern not found.

Pattern not found.

Pattern not found.

0x7ffff7fe3701

0x7ffff7fe3711

2 patterns found.

Pattern not found.

Pattern not found.

Pattern not found.

Pattern not found.

Pattern not found.

Pattern not found.

(gdb) info proc map


쳇 자기자신 가리키는 포인터 빼고는 안나온다.


그럼 ASLR 있을때 이 TLS 구조체가 로딩되는 위치가 뭔가 다른 라이브러리에 상대적으로 고정된 위치에 있는지 등등을 확인해보자.



Case1.

0x0000000000400515 in main ()

(gdb) x/20wx $rsp

0x7ffff5db0890: 0xf5db0980 0x00007fff 0x8ead5a00 0x2a734544

0x7ffff5db08a0: 0x00000000 0x00000000 0x926d776d 0x00007f19

0x7ffff5db08b0: 0x00000000 0x00000000 0xf5db0988 0x00007fff

0x7ffff5db08c0: 0x00000000 0x00000001 0x004004f4 0x00000000

0x7ffff5db08d0: 0x00000000 0x00000000 0x8c218a60 0xff4b4ded

(gdb) info proc map

process 3671

Mapped address spaces:


          Start Addr           End Addr       Size     Offset objfile

            0x400000           0x401000     0x1000        0x0 /var/www/a

            0x600000           0x601000     0x1000        0x0 /var/www/a

            0x601000           0x602000     0x1000     0x1000 /var/www/a

      0x7f19926b6000     0x7f199286b000   0x1b5000        0x0 /lib/x86_64-linux-gnu/libc-2.15.so

      0x7f199286b000     0x7f1992a6b000   0x200000   0x1b5000 /lib/x86_64-linux-gnu/libc-2.15.so

      0x7f1992a6b000     0x7f1992a6f000     0x4000   0x1b5000 /lib/x86_64-linux-gnu/libc-2.15.so

      0x7f1992a6f000     0x7f1992a71000     0x2000   0x1b9000 /lib/x86_64-linux-gnu/libc-2.15.so

      0x7f1992a71000     0x7f1992a76000     0x5000        0x0 

      0x7f1992a76000     0x7f1992a98000    0x22000        0x0 /lib/x86_64-linux-gnu/ld-2.15.so + 20A729

      0x7f1992c7f000     0x7f1992c82000     0x3000        0x0 

      0x7f1992c95000     0x7f1992c98000     0x3000        0x0 

      0x7f1992c98000     0x7f1992c99000     0x1000    0x22000 /lib/x86_64-linux-gnu/ld-2.15.so

      0x7f1992c99000     0x7f1992c9b000     0x2000    0x23000 /lib/x86_64-linux-gnu/ld-2.15.so

      0x7ffff5d92000     0x7ffff5db3000    0x21000        0x0 [stack]

      0x7ffff5dff000     0x7ffff5e00000     0x1000        0x0 [vdso]

  0xffffffffff600000 0xffffffffff601000     0x1000        0x0 [vsyscall]

(gdb) define mem_scan

Type commands for definition of "mem_scan".

End with a line saying just "end".

> find 0x400000, 0x400fff, $arg0

> find 0x600000, 0x600fff, $arg0

> find 0x601000, 0x601fff, $arg0

> find 0x7f19926b6000, 0x7f199286afff, $arg0

> find 0x7f199286b000, 0x7f1992a6afff, $arg0

> find 0x7f1992a6b000, 0x7f1992a6efff, $arg0

> find 0x7f1992a6f000, 0x7f1992a70fff, $arg0

> find 0x7f1992a71000, 0x7f1992a75fff, $arg0

> find 0x7f1992a76000, 0x7f1992a97fff, $arg0

> find 0x7f1992c7f000, 0x7f1992c81fff, $arg0

> find 0x7f1992c95000, 0x7f1992c97fff, $arg0

> find 0x7f1992c98000, 0x7f1992c98fff, $arg0

> find 0x7f1992c99000, 0x7f1992c9afff, $arg0

> find 0x7ffff5d92000, 0x7ffff5db2fff, $arg0

> find 0x7ffff5dff000, 0x7ffff5dfffff, $arg0

> find 0xffffffffff600000, 0xffffffffff600fffL, $arg0

>end

(gdb) 

(gdb) set $a="\x5a\xad"

(gdb) set $a[2]=0x8e

(gdb) mem_scan $a

Pattern not found.

Pattern not found.

Pattern not found.

Pattern not found.

warning: Unable to access target memory at 0x7f199286ee82, halting search.

Pattern not found.

Pattern not found.

Pattern not found.

Pattern not found.

Pattern not found.

0x7f1992c80729

1 pattern found.

Pattern not found.

Pattern not found.

Pattern not found.

0x7ffff5db0899

0x7ffff5db0c0a

2 patterns found.

Pattern not found.

Pattern not found.

(gdb) 





Case2.

(gdb) x/20wx $rsp

0x7fffac87d790: 0xac87d880 0x00007fff 0x39925f00 0xac3b5af6

0x7fffac87d7a0: 0x00000000 0x00000000 0xee24576d 0x00007faf

0x7fffac87d7b0: 0x00000000 0x00000000 0xac87d888 0x00007fff

0x7fffac87d7c0: 0x00000000 0x00000001 0x004004f4 0x00000000

0x7fffac87d7d0: 0x00000000 0x00000000 0x857966e3 0xf4877941

(gdb) info proc map

process 3650

Mapped address spaces:


          Start Addr           End Addr       Size     Offset objfile

            0x400000           0x401000     0x1000        0x0 /var/www/a

            0x600000           0x601000     0x1000        0x0 /var/www/a

            0x601000           0x602000     0x1000     0x1000 /var/www/a

      0x7fafee224000     0x7fafee3d9000   0x1b5000        0x0 /lib/x86_64-linux-gnu/libc-2.15.so

      0x7fafee3d9000     0x7fafee5d9000   0x200000   0x1b5000 /lib/x86_64-linux-gnu/libc-2.15.so

      0x7fafee5d9000     0x7fafee5dd000     0x4000   0x1b5000 /lib/x86_64-linux-gnu/libc-2.15.so

      0x7fafee5dd000     0x7fafee5df000     0x2000   0x1b9000 /lib/x86_64-linux-gnu/libc-2.15.so

      0x7fafee5df000     0x7fafee5e4000     0x5000        0x0 

      0x7fafee5e4000     0x7fafee606000    0x22000        0x0 /lib/x86_64-linux-gnu/ld-2.15.so + 20A729

      0x7fafee7ed000     0x7fafee7f0000     0x3000        0x0 

      0x7fafee803000     0x7fafee806000     0x3000        0x0 

      0x7fafee806000     0x7fafee807000     0x1000    0x22000 /lib/x86_64-linux-gnu/ld-2.15.so

      0x7fafee807000     0x7fafee809000     0x2000    0x23000 /lib/x86_64-linux-gnu/ld-2.15.so

      0x7fffac85e000     0x7fffac87f000    0x21000        0x0 [stack]

      0x7fffac8c9000     0x7fffac8ca000     0x1000        0x0 [vdso]

  0xffffffffff600000 0xffffffffff601000     0x1000        0x0 [vsyscall]

(gdb) define mem_scan

Type commands for definition of "mem_scan".

End with a line saying just "end".

> find 0x400000, 0x400fff, $arg0

> find 0x600000, 0x600fff, $arg0

> find 0x601000, 0x601fff, $arg0

> find 0x7fafee224000, 0x7fafee3d8fff, $arg0

> find 0x7fafee3d9000, 0x7fafee5d8fff, $arg0

> find 0x7fafee5d9000, 0x7fafee5dcfff, $arg0

> find 0x7fafee5dd000, 0x7fafee5defff, $arg0

> find 0x7fafee5df000, 0x7fafee5e3fff, $arg0

> find 0x7fafee5e4000, 0x7fafee605fff, $arg0

> find 0x7fafee7ed000, 0x7fafee7effff, $arg0

> find 0x7fafee803000, 0x7fafee805fff, $arg0

> find 0x7fafee806000, 0x7fafee806fff, $arg0

> find 0x7fafee807000, 0x7fafee808fff, $arg0

> find 0x7fffac85e000, 0x7fffac87efff, $arg0

> find 0x7fffac8c9000, 0x7fffac8c9fff, $arg0

> find 0xffffffffff600000, 0xffffffffff600fffL, $arg0

>end

(gdb) 

(gdb) set $a="\x5f\x92"

(gdb) set $a[2]=0x39

(gdb) mem_scan $a

Pattern not found.

Pattern not found.

Pattern not found.

Pattern not found.

warning: Unable to access target memory at 0x7fafee3dce82, halting search.

Pattern not found.

Pattern not found.

Pattern not found.

Pattern not found.

Pattern not found.

0x7fafee7ee729

1 pattern found.

Pattern not found.

Pattern not found.

Pattern not found.

0x7fffac87d799

0x7fffac87db0a

2 patterns found.

Pattern not found.

Pattern not found.

(gdb) x/10wx 0x7fafee7ee720

0x7fafee7ee720: 0x00000000 0x00000000 0x39925f00 0xac3b5af6

0x7fafee7ee730: 0xbca0c2bc 0xb371fa43 0x00000000 0x00000000

0x7fafee7ee740: 0x00000000 0x00000000

(gdb) info proc map

process 3650

Mapped address spaces:


          Start Addr           End Addr       Size     Offset objfile

            0x400000           0x401000     0x1000        0x0 /var/www/a

            0x600000           0x601000     0x1000        0x0 /var/www/a

            0x601000           0x602000     0x1000     0x1000 /var/www/a

      0x7fafee224000     0x7fafee3d9000   0x1b5000        0x0 /lib/x86_64-linux-gnu/libc-2.15.so

      0x7fafee3d9000     0x7fafee5d9000   0x200000   0x1b5000 /lib/x86_64-linux-gnu/libc-2.15.so

      0x7fafee5d9000     0x7fafee5dd000     0x4000   0x1b5000 /lib/x86_64-linux-gnu/libc-2.15.so

      0x7fafee5dd000     0x7fafee5df000     0x2000   0x1b9000 /lib/x86_64-linux-gnu/libc-2.15.so

      0x7fafee5df000     0x7fafee5e4000     0x5000        0x0 

      0x7fafee5e4000     0x7fafee606000    0x22000        0x0 /lib/x86_64-linux-gnu/ld-2.15.so

      0x7fafee7ed000     0x7fafee7f0000     0x3000        0x0 

      0x7fafee803000     0x7fafee806000     0x3000        0x0 

      0x7fafee806000     0x7fafee807000     0x1000    0x22000 /lib/x86_64-linux-gnu/ld-2.15.so

      0x7fafee807000     0x7fafee809000     0x2000    0x23000 /lib/x86_64-linux-gnu/ld-2.15.so

      0x7fffac85e000     0x7fffac87f000    0x21000        0x0 [stack]

      0x7fffac8c9000     0x7fffac8ca000     0x1000        0x0 [vdso]

  0xffffffffff600000 0xffffffffff601000     0x1000        0x0 [vsyscall]

(gdb) 



오오 ㅋㅋ 실험해보니 /lib/x86_64-linux-gnu/ld-2.15.so 의 R-X 세그먼트 베이스주소에서 항상 일정한 오프셋에 떨어져있다.


오프셋은. 20A720


이건아마 시스템마다 다르겠지만... 

근데 ld.so 의 베이스주소는 어떻게 알아낼수있나?


뭐 당연히 PLT 의 최상단에 있는 다이나믹 로더의 주소가 ld.so 내부를 포인팅하므로 여기서부터 TLS 까지의 오프셋도 고정일것이다. ㅋㅋ


0x600fe0: 0x00000000 0x00000000 0x00600e50 0x00000000

0x600ff0 <_GLOBAL_OFFSET_TABLE_+8>: 0x92c9a2c8 0x00007f19 0x92a8b200 0x00007f19

0x601000 <puts@got.plt>: 0x92726ce0 0x00007f19 0x926d7680 0x00007f19

0x601010 <data_start>: 0x00000000 0x00000000 0x00000000 0x00000000

0x601020 <completed.6531>: 0x00000000 0x00000000 0x00000000 0x00000000


즉, ld.so 의 버전을 정확히 알고 GOT 릭할수있으면 카나리값을 알수있을뿐만 아니라 메모리 쓰기가 가능하다면 조작까지 가능하다. 아마 x86 도 거의 비슷하겠지...