Cookie

'Wargame > Natas:OverTheWire' 카테고리의 다른 글

[Natas] Level7  (0) 2016.10.22
[Natas] Level6  (0) 2016.10.22
[Natas] Level4  (0) 2016.10.22
[Natas] Level3  (0) 2016.10.22
[Natas] Level2  (0) 2016.10.22

PythonChallenge

Level5




산입니다.

발음해보라고 하네요.

무슨 소린지 당최 모르겠습니다.

소스를 확인해보도록하죠.



peak hell과 발음이 비슷하다고 합니다.



banner.p를 확인해보니 알 수 없는 문자들이 나열 되어 있네요.

검색 해 보니 .p 확장자는 파이썬의 pickle로 추출한 파일 확장자라는 것을 알 수 있었습니다.



pickle 모듈을 이용하여 복구를 해 보니 위와 같은 리스트가 나타났습니다.

첫 번째는 95라는 숫자가 있고, 2번째부터는 모든 숫자를 더하면 95가 나왔습니다.

아마 출력을 하는 듯 합니다.



출력하는 스크립트를 작성하였습니다.



짠! channel이라는 단어가 나타났습니다!


[*] FLAG : channel.html

'Wargame > PythonChallenge' 카테고리의 다른 글

[PythonChallenge] Level7  (0) 2017.02.14
[PythonChallenge] Level6  (0) 2016.06.28
[PythonChallenge] Level4  (0) 2016.06.27
[PythonChallenge] Level3  (0) 2016.06.27
[PythonChallenge] Level2  (0) 2016.06.27

SuNiNaTaS

Web Level5




5번째 문제입니다. 문자열을 체크하는 웹페이지인데, 소스를 확인 해 보도록 하죠.



빨간 네모 박스를 보면 js가 패킹되어있는 것을 확인 할 수 있는데, http://jsbeautifier.org/ 에 넣어주면 깔끔하게 언패킹 됩니다.



PASS라는 함수가 선언이 되어있네요.

파이썬으로 복호화 루틴을 짜서 돌려보는 방법도 있지만, 개발자 도구의 콘솔 기능을 이용하여 바로 PASS의 결과값을 도출 해 내도록 하겠습니다.



힌트에 나와있는 수를 PASS 함수에 넣어주니 9c43c20c 라는 16진수가 나타났습니다.



해당 값을 check 해 주면 Auth Key를 뱉어줍니다.

'Wargame > SuNiNaTaS' 카테고리의 다른 글

SuNiNaTaS Web Level7  (0) 2016.05.09
SuNiNaTaS Web Level6  (0) 2016.05.09
SuNiNaTaS Web Level4  (3) 2016.05.07
SuNiNaTaS Web Level3  (0) 2016.05.06
SuNiNaTas Web Level2  (0) 2016.05.06
OverTheWire_Wargame Narnia

[ level5 -> level6 ]




자, level5입니다. 문제를 까 보니 i와 buffer 변수가 선언 되어 있으며, i 변수를 500으로 바꾸면 쉘을 띄워주겠다고 합니다.

buffer 변수는 [buffer의 크기-1]의 위치에 NULL을 집어넣기 때문에 overflow는 시키기 어려울 것 같습니다.

그래서 구글링을 잘 해보니 snprintf에 FSB가 존재한다고 합니다. snprintf는 출력 할 때 printf처럼 표준 출력을 사용하지 않고 문자열 자체로 출력하기 때문에 %x와 같은 서식문자도 buffer에 집어 넣을 수 있는 것입니다.

FTZ 이후로 기억 속에서 잊혀져 가던 FSB를 문서를 다시 보면서 어렴풋이 되찾았습니다.

차근차근 실행 해 가면서 보도록 하죠.



먼저 buffer 변수에 문자열을 집어 넣어봤습니다.

버퍼의 총 길이와 입력한 argv[1]의 값을 출력 해 주고, i의 값과 i의 주소를 뱉어냅니다.



여기서 argv[1]에 %x를 입력 해 줍니다.

그러면 snprintf에 의해 %x 문자열 자체가 buffer에 넘어가게 되고, 이를 printf에서 그대로 인자로 전달 해 줘서 %x에 해당하는 인자값을 출력해줍니다.



그럼, AAAA를 인자로 전달하고(printf의 첫 번째 인자) %x를 연달아 쓰면서 해당 인자 값이 몇 번째에 출력 되는 지 확인 해 보았습니다.

%x를 총 5번 사용했을 때 AAAA에 해당하는 값이 출력이 되었습니다.

그럼 이 위치를 이용해 FSB를 시도 해 보도록 하죠.

payload는 아래와 같습니다.


payload :

./narnia5 AAAA+[i의 주소]+%8x%8x%8x%8x+%460c%n


여기서 %460c를 입력 해 준 이유는 앞에 나온 'AAAA'와 i의 주소, %8x의 4번 출력으로 인해 8byte * 5 = 40byte이기 때문에 500에서 40을 빼서 460이 된 것입니다.

또한, i의 주소 앞에 'AAAA'를 붙여주는 이유는 %n이라는 서식문자 자체가 esp+4의 위치(다음 스택)에 있는 주소의 값을 수정해 주기 때문입니다.

그럼 계속 실행 해 보도록 하죠.



앞서 나온 buffer의 크기가 늘어났기 때문에 i의 위치가 변동되었습니다.

0xffffd6dc -> 0xffffd6cc로 바꿔주도록 하죠.



짜잔! key값을 얻어냈습니다.






References

- Format String Bug(HackerLogin 서정현 선배님)

- Format String Attacks(Tim Newsham)

OverTheWire_Wargame Narnia

[ level4 -> level5 ]



이번에는 환경변수를 사용하지 못하도록 NULL Byte를 채워 넣는 Egg hunter가 추가된 BOF 문제입니다.

스택의 주소는 이전과 동일하게 고정적이므로 nop sled와 shellcode를 이용하여 풀이하겠습니다.



먼저 값을 충분히 집어넣어 segmentation fault가 터지는 지점을 찾아냈습니다.

272바이트를 입력했을 경우 segmentation fault가 나타나는데, 이는 SFP가 0x91919191로 덮어져 잘못된 주소로 리턴했기 때문에 나타나는 증상이죠.

그러므로 buffer+272의 위치가 return address입니다.



shellcode는 24byte짜리 shellcode를 사용 할 것이며, 272 - 24 = 248byte 만큼을 0x90으로 채워주고 리턴 할 위치를 찾아보도록 하겠습니다.



ebp+0x0c에서 +4만큼의 위치에 있는 argv[1]의 값을 찾아냈습니다.

그 중 0xffffd7df를 return address로 잡도록 하겠습니다.


return address : 0xffffd7df



payload :

./narnia4 0x90*248 + shellcode(24byte) + 0xffffd7df



짜잔!

OverTheWire_Wargame Leviathan

[ level5 -> level6 ]




자, 벌써 level5입니다. 홈 디렉토리를 확인하니 leviathan5라는 바이너리가 딱 버티고 있습니다.

권한을 확인 해 보니 이번에도 setuid bit가 걸려있네요. leviathan6 권한으로 실행이 되나봅니다. 파일을 실행 해 보니 "Cannot find /tmp/file.log"라는 오류 메시지를 내뱉고 프로그램을 종료시킵니다. 어떤 이유인지 확인하기 위해 gdb로 까보도록 하죠.



main 함수를 disassemble 한 상태입니다. 맨 처음에 fopen으로 파일 하나를 오픈 한 후, 해당 파일이 없으면 오류메시지를 내뱉고 프로그램을 종료시킵니다.

만약 파일이 있을 경우에는 fgetc와 feof 함수를 이용해 파일의 끝까지 이동하면서 한 바이트씩 읽어가며, 도중 putchar을 이용해 읽었던 값을 출력해줍니다.

그리고 eof에 도달하면 반복을 종료하고, getuid, setuid 함수를 이용해 현재 함수의 uid를 얻어와 setuid시키며 0x8048722에 들어있는 문자열을 인자로 unlink합니다.

fopen 할 때 인자로 전달하는 값 중 첫 번째 인자와 unlink 할 때 전달하는 인자가 동일합니다. 즉, fopen 하는 파일은 이 프로그램을 실행시키고 끝까지 실행됨과 동시에 삭제가 된다는 소리가 되겠네요.

상수 값을 분석해 본 결과, fopen의 두 번째 인자는 "r", 첫 번째 인자는 "/tmp/file.log"였습니다. 따라서 /tmp/file.log 파일을 읽어서 fgetc로 한 글자씩 저장하고, 출력하는 행위를 eof를 만날 때 까지 한다는 소리가 되겠네요.

그렇다면 /etc/leviathan_pass/leviathan6를 /tmp/file.log에 심볼릭 링크하여 leviathan5 프로그램을 실행시키면 해결 될 것 같습니다.



leviathan6로 통하는 패스워드를 아름답게 내뱉어주네요.

OverTheWire_Wargame Leviathan

[ level3 -> level4 ]




이번 문제는 trash 폴더가 숨김 속성으로 꽁꽁 숨어있었습니다. 해당 폴더로 들어가서 ls를 때려주면 bin이라는 바이너리가 존재하는데, 실행시켜보니 다수의 2진코드들이 나타났습니다. 일단 gdb로 분석 해 보도록 하죠.



일단 시작하자마자 fopen으로 파일 하나를 열어둡니다. 그리고 fgets 함수로 어떤 값을 받네요. 그리고 putchar 함수가 있는 것을 보니, putchar 함수를 통해 한 바이트씩 출력을 해 주는 것 같습니다.

fopen을 호출 할 때 상수값을 이용하여 인자를 입력받기 때문에 해당 상수에 어떤 값이 들어있는 지 확인해보도록 합시다.




fopen 함수는 f = fopen("/etc/leviathan_pass/leviathan5", "r"); 와 같이 실행이 된 모양입니다.

그리고 곧바로 if함수로 해당 FILE 포인터(ex. f)가 존재하지 않을 경우(파일이 존재하지 않을 경우) 프로그램을 즉시 종료시킵니다.

정상적으로 파일이 열렸을 경우에는 fgets로 값을 입력받는데, if문에서 FILE 포인터를 검사 할 때 사용했던 [esp+0x1c]를 다시 사용하는 것을 보니, leviathan5로 통하는 패스워드가 들어있는 파일을 읽어내는 듯 합니다.

분석해보면 fgets(buffer, 256, f); 와 같이 사용을 한 것 같습니다.

그리고 아래쪽으로 jmp 등으로 분기하는 부분이 여럿 있는데, 디버깅 능력이 부족하다 보니 이것까지 분석을 하지는 못했습니다.

하지만 putchar 함수를 이용하여 1바이트씩 찍어내는 부분이 있으며, 따로 암호화 하는 부분은 보이지 않기 때문에 해당 파일의 내용을 1바이트씩 출력한 것으로 예상하고 값을 찾아냈습니다.


01010100 : 0x54 : T

01101001 : 0x69 : i

01110100 : 0x74 : t

01101000 : 0x68 : h

00110100 : 0x34 : 4

01100011 : 0x63 : c

01101111 : 0x6f : o

01101011 : 0x6b : k

01100101 : 0x65 : e

01101001 : 0x69 : i

00001010 : 0x0a : 개행


Tith4cokei


Leviathan5 계정의 패스워드로 위 문자열을 집어 넣었더니 정상적으로 접속이 되었습니다.





OverTheWire_Wargame Bandit


[ level5 -> level6 ]



자, 이번 문제는 힌트를 한번 참고해서 풀어보도록 하죠.

이번 레벨의 목표는 inhere 디렉토리 안에 1033바이트의 읽을 수 있는 non-exec 파일이 있다고 합니다.

직접 확인해보도록 하죠.


inhere 디렉토리 아래에는 여러개의 디렉토리가 또 존재하고 있으며, 이 디렉토리 아래에는 여러개의 파일이 더 존재합니다. 그러나 우리는 찾고자 하는 파일이 1033바이트인 것을 이미 알고 있기 때문에 find 명령어로 size 옵션을 지정해주어 1033바이트인 파일만 추려냈습니다.

그러면 key값을 바로 확인 할 수 있습니다.

OverTheWire_Wargame Bandit

[ level4 -> level5 ]



이번 문제도 level3와 동일하게 inhere 라는 디렉토리가 있습니다.

해당 폴더로 친절하게 들어가주면 -file* 이름으로 여러개의 파일이 있습니다.

처음에는 바이너리를 merge시키는 문제인 줄 알았지만, 해당 폴더에 쓰기 권한이 없기 때문에 그냥 전체 파일을 출력 해 주었더니 마지막에 있는 key값을 찾아 낼 수 있었습니다.

+ Recent posts