referer
'Wargame > Natas:OverTheWire' 카테고리의 다른 글
[Natas] Level6 (0) | 2016.10.22 |
---|---|
[Natas] Level5 (0) | 2016.10.22 |
[Natas] Level3 (0) | 2016.10.22 |
[Natas] Level2 (0) | 2016.10.22 |
[Natas] Level1 (0) | 2016.10.22 |
referer
[Natas] Level6 (0) | 2016.10.22 |
---|---|
[Natas] Level5 (0) | 2016.10.22 |
[Natas] Level3 (0) | 2016.10.22 |
[Natas] Level2 (0) | 2016.10.22 |
[Natas] Level1 (0) | 2016.10.22 |
PythonChallenge
Level4
???
뭔지 모르겠습니다.
소스를 한번 확인해봅시다.
400번 이상 시도하랍니다.
nothing 파라미터에 12345를 주고 요청을 때려봅시다.
다음 nothing 번호를 알려주네요.
400번 다 입력하다가 날새기는 싫죠?
스크립트로 돌려줍시다.
16044에서 2로 나누랍니다.
8022로 주고 다시 돌려봅시다.
82682에서 숫자를 잘못 읽었답니다. 다음 숫자는 63579라네요.
주욱 돌려주다 보면 다음 레벨의 플래그가 나타납니다.
[*] FLAG : peak.html
[PythonChallenge] Level6 (2) | 2016.06.28 |
---|---|
[PythonChallenge] Level5 (2) | 2016.06.27 |
[PythonChallenge] Level3 (2) | 2016.06.27 |
[PythonChallenge] Level2 (0) | 2016.06.27 |
[PythonChallenge] Level1 (0) | 2016.06.27 |
SuNiNaTaS
Web Level4
4번째 문제입니다. Plus 버튼과 User-Agent, Auth key가 명시되어있습니다. 아마 User-Agent를 조작하여 다른 이름으로 변환시키는 문제인 것 같습니다.
소스를 보도록 하죠.
맨 아래 힌트 부분을 확인 해 보니 Point를 50으로 만들고 'SuNiNaTaS'를 어떻게 하라고 나와있는데, 역시 User-Agent를 SuNiNaTaS로 바꾸도록 유도하는 문제인 것 같습니다.
파이썬으로 소스를 짜서 변조 해 보도록 하죠.
소스에서 알 수 있듯이, Plus 버튼을 누르면 web04_ck.asp로 넘어가게 되며, 여기서 Point를 1 더해주는 형식입니다. 그래서 총 60번을 돌리면서 Auth Key에 있는 '?????'가 문자열로 표시 되었을 경우 해당 response 값을 출력하는 스크립트를 작성했습니다.
하지만 이렇게 돌렸을 경우, Point가 한번에 50까지 오르지 않고 10씩 올라가는 것을 확인 할 수 있었는데, DoS를 방지하기 위해 10번 참조하면 쉬도록 만들어 놨나 봅니다.
총 5번 스크립트를 돌렸을때 아래와 같은 응답값을 뱉어냈습니다.
Auth Key의 값이 ?????에서 문자열로 바뀌었습니다.
SuNiNaTaS Web Level6 (2) | 2016.05.09 |
---|---|
SuNiNaTaS Web Level5 (8) | 2016.05.09 |
SuNiNaTaS Web Level3 (2) | 2016.05.06 |
SuNiNaTas Web Level2 (2) | 2016.05.06 |
SuNiNaTas Web Level1 (0) | 2016.05.06 |
이번에는 환경변수를 사용하지 못하도록 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 Narnia [level6 -> level7] (0) | 2016.01.19 |
---|---|
OverTheWire Narnia [level5 -> level6] (0) | 2016.01.19 |
OverTheWire Narnia [level3 -> level4] (0) | 2016.01.17 |
OverTheWire Narnia [level2 -> level3] (0) | 2016.01.14 |
OverTheWire Narnia [level1 -> level2] (0) | 2016.01.14 |
Level3의 문제입니다.
R/W 권한과 READ ONLY의 권한으로 파일을 각각 하나씩 open 해줍니다.
output 하는 경로의 경우 "/dev/null"로 고정이 되어있네요. input의 경우에는 사용자에게 직접 입력을 받습니다. 이 때, 입력은 argv[1]로 받으며 strcpy 함수를 이용하기 때문에 길이 제한이 없습니다. 따라서 이 때 BOF가 발생하게 되는데, ofile은 값을 지정해줬음에도 불구하고 ifile보다 먼저 선언되었기 때문에 ifile에서 32바이트를 넘어가는 길이의 입력을 받을 경우 ofile의 값에도 영향을 미치게 됩니다.
이러한 스택의 특성을 이용하여 level4로 갈 수 있는 패스워드를 따 보도록 합시다.
일단 ifile의 경우 overflow를 시키면 ofile의 값을 덮어씌우게 되는데, 이럴 경우 ofile의 포인터는 overflow 된 ifile의 중간에 위치하게 됩니다. 따라서 아래와 같은 payload를 사용하면 두 개의 파일에 따로따로 접근 할 수 있게 됩니다.
ifle과 ofile을 이어 붙인 그림입니다.
입력을 받을 수 있는 argv[1]에는 ///////////////////tmp/fstr3am_/tmp/fstr3am_/a 를 넣어줍니다.
그럼 첫 번째 fstr3am_ 이후의 위치가 원래 ofile의 시작 포인터입니다. 따라서 ofile을 끄집어 낼 경우 /tmp/fstr3am_/a가 딸려나오게 됩니다.
그리고 ifile을 꺼낼 경우 원래 ifile의 길이인 24byte를 초과했기 때문에 ofile의 마지막인 a 이후에 나오는 NULL Byte까지 인식을 하여 /tmp/fstr3am_/tmp/fstr3am_/a이 ifile의 전체 경로가 됩니다.
그렇다면 /tmp/fstr3am_/tmp/fstr3am_/ 의 경로에 /etc/narnia_pass/narnia4의 symbolic link를 걸어준 a라는 이름의 파일을 생성해주고, /tmp/fstr3am_/ 의 경로에 비어있는 a라는 파일을 하나 만들어주면 /tmp/fstr3am_/a에 level4로 통하는 패스워드가 복사 될 것입니다.
위와 같이 a라는 파일을 두 개 만들어줍니다.
그리고 위에서 설명했던 payload대로 입력을 해 주면 패스워드가 출력됩니다.
OverTheWire Narnia [level5 -> level6] (0) | 2016.01.19 |
---|---|
OverTheWire Narnia [level4 -> level5] (0) | 2016.01.17 |
OverTheWire Narnia [level2 -> level3] (0) | 2016.01.14 |
OverTheWire Narnia [level1 -> level2] (0) | 2016.01.14 |
OverTheWire Narnia [level0 -> level1] (0) | 2016.01.14 |
이번 문제는 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 Leviathan [level6 -> level7] (0) | 2016.01.13 |
---|---|
OverTheWire Leviathan [level5 -> level6] (0) | 2016.01.13 |
OverTheWire Leviathan [level3 -> level4] (0) | 2016.01.13 |
OverTheWire Leviathan [level2 -> level3] (0) | 2016.01.11 |
OverTheWire Leviathan [level1 -> level2] (0) | 2016.01.11 |
Leviathan3로 접속을 하면 홈 디렉토리에 level3 바이너리가 우릴 기다리고 있습니다. 해당 바이너리는 leviathan4 권한으로 setuid bit가 걸려있기 때문에 이번 레벨은 level3 바이너리로 풀어내면 될 것 같습니다. 한 번 실행 시켜 보도록 하죠.
바이너리를 실행시키면 패스워드를 요구하는데, 패스워드가 틀렸을 때 오류 메시지를 내뱉고 프로그램을 즉시 종료시킵니다.
긴 문자열을 보내도 segmentation fault같은 메시지를 안 내뱉는 것을 보니 BOF 유형은 아닌 것 같아 보입니다. gdb로 분석해보도록 합시다.
main 함수를 disassemble 한 상태입니다. 중간에 보면 printf로 0x804878f에 들어 있는 정보를 출력합니다. 확인 해 보니 해당 문자열은 "Enter the password> " 였습니다. 이 문자열은 우리가 바이너리를 실행시켰을 때 패스워드를 입력받기 직전에 내뱉는 문자열이었습니다. 따라서 그 이후에 진입하년 do_stuff 함수에 패스워드를 입력 및 비교하는 루틴이 들어 있을 것이라고 예상 할 수 있겠습니다.
그렇다면 do_stuff 함수도 분석 해 보도록 합시다.
중간에 보면 strcmp 함수를 호출하는 것을 볼 수 있습니다. 또한, strcmp 이후 if문의 조건을 통해 루틴을 분기시키는 부분이 있네요. strcmp를 통해 패스워드 일치/불일치 여부를 확인 한 후 이 if문에서 프로그램을 종료시킬 지, 다음 루틴으로 넘어갈 지 판별하는 듯 합니다.
또한, 조금 더 아래쪽을 살펴보면 system 함수가 호출되는 것을 확인 할 수 있는데, 위의 mov 명령을 통해 esp에 들어있는 주소의 문자열을 인자로 함수를 실행시킵니다.
strcmp 함수와 system 함수의 인자에는 어떤 값들이 전달되는 지 확인해보도록 합시다.
strcmp 함수의 1, 2번 인자는 우리가 입력한 문자열과 "snlprintf"입니다. 즉, 우리가 입력한 문자열이 snlprintf일 경우 프로그램을 종료시키지 않고 다음 루틴을 실행한다는 뜻이 되겠죠. 그리고 값이 동일할 경우 0x8048760에 들어있는 문자열을 출력 한 후 0x8048774에 들어있는 문자열을 인자로 system 함수를 실행시킵니다. 0x8048760은 "[You've got shell]!", 0x8048774는 "/bin/sh"인 것을 보니, snlprintf를 입력받았을 경우 전자의 문자열을 출력하고 쉘을 띄워주는 프로그램인 것 같습니다. gdb를 종료하고 프로그램을 실행시켜봅시다.
leviathan4로 통하는 패스워드를 깔끔하게 뱉어줍니다.
OverTheWire Leviathan [level5 -> level6] (0) | 2016.01.13 |
---|---|
OverTheWire Leviathan [level4 -> level5] (0) | 2016.01.13 |
OverTheWire Leviathan [level2 -> level3] (0) | 2016.01.11 |
OverTheWire Leviathan [level1 -> level2] (0) | 2016.01.11 |
OverTheWire Leviathan [level0 -> level1] (0) | 2016.01.11 |
OverTheWire_Wargame Bandit
[ level4 -> level5 ]
이번 문제도 level3와 동일하게 inhere 라는 디렉토리가 있습니다.
해당 폴더로 친절하게 들어가주면 -file* 이름으로 여러개의 파일이 있습니다.
처음에는 바이너리를 merge시키는 문제인 줄 알았지만, 해당 폴더에 쓰기 권한이 없기 때문에 그냥 전체 파일을 출력 해 주었더니 마지막에 있는 key값을 찾아 낼 수 있었습니다.
OverTheWire Bandit [level6 -> level7] (0) | 2016.01.10 |
---|---|
OverTheWire Bandit [level5 -> level6] (0) | 2016.01.10 |
OverTheWire Bandit [level3 -> level4] (0) | 2016.01.10 |
OverTheWire Bandit [level2 -> level3] (0) | 2016.01.10 |
OverTheWire Bandit [level1 -> level2] (0) | 2016.01.10 |
OverTheWire_Wargame Bandit
[ level3 -> level4 ]
Level3에 들어오면 inhere라는 이름의 디렉터리가 존재합니다. 들어가고 싶게 생기지 않았나요? 들어가줍시다.
ls 명령어로 확인했을 때 아무것도 나타나지 않는데, 우리의 촉은 숨김파일이 있다! 라고 말해주죠.
ls -al 명령어로 확인 해 보니 hidden이라는 숨김파일이 존재합니다.
해당 파일을 cat 명령어로 보면 다음 level로의 key 값을 찾아낼 수 있습니다.
OverTheWire Bandit [level5 -> level6] (0) | 2016.01.10 |
---|---|
OverTheWire Bandit [level4 -> level5] (0) | 2016.01.10 |
OverTheWire Bandit [level2 -> level3] (0) | 2016.01.10 |
OverTheWire Bandit [level1 -> level2] (0) | 2016.01.10 |
OverTheWire Bandit [level0 -> level1] (0) | 2016.01.10 |