CrackMe02 에서 VB 덕분에 좌절을 맛보고

앞으로 어떻게 하지 하다가 그냥 계속 풀어보기로 했습니다..

다행히 03은 01과 구성이 비슷해서 손 쉽게 풀어볼 수 있었내요

 

 

먼저 심플스에서 요구한 문제는 아래와 같내요 

키파일의 사이즈는 몇 바이트인가

일단 실행을 해보겠습니다.

      

메시지 창이 두 번 뜨더니 그냥 끝이 나는 프로그램이내요.

첫 번째 메시지는 .. 확인 버튼을 누르면 키파일을 체크한다는 것 같내요

확인을 눌렀을 때 나오는 두 번째 메시지는 찾은 파일이 유효한 키파일이 아니라는거 같내요

 

실행시켰을 때 사용자가 마땅히 더 할게 없어보이니 바로 올리디버거로 까(?)보겠습니다.

까보면 01 때 처럼 눈에 확 들어오는 영단어들이 많이 보입니다. 마음이 편하죠..

까보면 01 때 봤던 MessageBoxA가 보이내요

첫 번째 메시지를 띄울 때 사용된 것 같습니다.

이 API는 특별히 설명할게 없으니 넘어가겠습니다.

그 다음 아래로 내려오면 CreateFileA 라는 API가 보입니다.

MSDN 공식홈에 있는 것 중에 필요 할 것 같은 것을 캡쳐해왔내요

 

대충 보면 이 API는 어떠한 파일을 오픈하거나 새로만드는 듯하내요

MSDN 내용을 보다보니 OPEN_EXISTING 에 대한 설명이 있는데요

올리디버거의 API부분을 잘 보면 OPEN_EXISTING이라고 써져있는 곳이 있습니다.

아무래도 MSDN에서 가져온 부분은 이 API가 사용하는 모드에 대한 내용인 것 같내요

그렇다면 문제에서는 이 API의 OPEN_EXISTING 모드를 사용하고 있다는걸 알게 됬내요

대략 모드 내용을 보면 파일이나 장치가 '있다면' 오픈을 하는 것 같습니다.

캡쳐화면을 보면 모드 이름 밑에 숫자가 써있는데 아마 해당 모드에 대한 번호인 것 같습니다.

그런데 올리디버거를 잘 보면 Mode = OPEN_EXISTING라고 써있는 줄에

PUSH 3 이라고 써져있습니다.

MSDN 설명상에 OPEN_EXISTING의 모드 번호도 3번이구요

뭔가 서로 연관되어있다는 것 같다라고 생각하고 넘어가겠습니다.

내려오다보면 getfilesize라는 API가 사용되고 있는 걸 볼 수 있는대요

MSDN에서 보면 특정 파일의 크기를 byte단위로 알려주는 API인 것 같내요.

아마 CreateFile API로 생성된 파일의 크기를 알기 위해서 사용하는 것 같습니다.

그 후론 MessageBox만 나오내요.

 

이제 어셈블리어 부분을 볼껀데요

개인적인 생각으로 초반 크랙미 풀이의 핵심은 어셈블리어쪽에 있는 비교하는 부분이나

점프만 잘 봐도 손 쉽게 풀 수 있을 것 같내요

이 문제에서 바로 찾을 수 있는 비교하는 곳에는 CMP가 사용되고 있는대요

CreateFile API 바로 아래 부분과 getfilesize API 아래 부분에서 사용되고 있내요

 

 

먼저 CreateFile API 밑에 있는 CMP를 보면 EAX의 값과 -1을 비교하고 있습니다.

바로 아래는 JE가 사용되어 두 값이 같다면 00401075로 이동하게 되어있내요

실제로 이 문제파일을 아무 작업없이 그냥 실행을 하면 EAX에는 -1 값이 들어가게 됩니다.

 

 

아무 작업을 하지 않고 실행했을 때 EAX의 모습입니다.

보면 EAX에 FFFF FFFF가 들어가있는걸 볼 수 있는데 이 값은 Hex 값이고 이 값을

10진수로 바꿔보면 -1이라는 것을 알 수 있습니다.

그럼 CMP의 결과는 두 값이 같다고 나오고 JE는 두 값이 같기 때문에 실행이 되겠죠

JE가 실행이 안되야 원하는 메시지 창이 출력될텐데 말이죠

그럼 우선 이 CMP가 참이 되지않도록 CreateFile 실행 이후 EAX의 값이 -1이 되면 안된다는 걸 알았습니다.

EAX는 함수나 연산 후 값이 저장되는 곳이니 아마 -1이라는 값은 CreateFile API의 리턴값이라는 걸 알 수 있습니다.

현 상태에서 CreateFile API는 모드3번, 그러니까 OPEN_EXISTING을 사용하는데

이 모드는 위에 써놨듯이 파일이나 장치가 존재해야만이 정상작동을 합니다.

근데 지금 상태에는 이 문제에서 사용할 파일이 존재하지 않죠.

CreateFile API 부분을 잘 보면 친절하게도 FileName=abex.l2c라고 파일명을 알려주고 있내요.

이 파일명을 가진 파일을 크랙미 문제 파일과 같은 경로에 메모장이나 여러방법으로 생성해주면 되겠내요.

그러면 첫 번째 CMP부분을 지나갈 수 있습니다.

하지만 제가 여기서 궁금했던건 위에 언급했던 PUSH 3에 대한 것이었습니다.

3번 모드인 OPEN_EXISTING이 설정되는 부분에서 스택에 3이라는 값을 넣는다는건 왠지 3번 모드를 사용하겠다고

설정한걸 스택에 저장해두려는 것 같았거든요.

그래서 혹시나하고 다른 숫자를 넣어보기로 해봤습니다.

MSDN에 있는걸 참고해서 OPEN_ALWAYS의 번호인 4를 넣어보기로 했습니다.

이 모드는 파일일이 있다면 덮어쓰고 없으면 새로 생성하는 모드인 것 같더라구요

 

 

기존 PUSH 3을 PUSH 4로 바꿔서 실행시켜 봅니다. 

 

 

그러면 아까와는 다르게 EAX에 FFFF FFFF가 아닌 0000 01D4라는 값이 들어갔습니다.

그리고 잘 보면 그 값이 바로 아래 GetFileSize API 안에 들어가는 걸 볼 수 있는대요

 

아무래도 CreateFile로 생성된 파일과 관련된 어떠한 주소가 아닌가 싶습니다.

어쨌든 PUSH 3 부분의 값을 MSDN에서 알려주고 있는 다른 숫자로 바꿔도 작동 하는걸로 봐서

이 PUSH 부분이 CreateFile의 설정(다르게는 옵션?)을 스택에 밀어넣고 있는 것 같내요

 

abex.l2c 라는 파일을 직접 생성했든, 저 처럼 모드를 바꿔서 생성했든

이제 문제 파일과 같은 경로에 abex.l2c 라는 파일이 생성되어있는걸 볼 수 있습니다.

그럼 이제 더이상 CMP EAX, -1은 신경쓰지 않아도 되겠내요

여기서 끝이라면 좋겠지만 ... 일단 그냥 실행시켜 보겠습니다.

 

 

간단하게 이 파일이.. 아니라내요

해서 다시 한 번 올리디버거를 보면 GetFileSize API가 실행된 직 후 다시 한 번 더 CMP가 나옵니다.

 

 

보면 CMP EAX, 12 라고 되어있는데요

API 실행 직 후니까 EAX에는 아마도 실행됬던 GetFileSize의 반환값이 저장되어있겠내요

그럼 이 API의 반환값은 Byte 단위니까 파일 크기가 12Byte면 되겠내요

라고 생각하고 처음에 했다가 안되서 뭔지 모르고 헤맸었내요.

CMP EAX, 12에 써있는 이 '12'는 흔히 알고 있는 10진수의 숫자가 아니라 16진수로 써있던거였내요

16진수로 '12'는 10진수의 '18'에 해당하니 이 CMP에서 비교하는 걸 10진수로 쓰자면

CMP EAX, 18(10)이 되겠내요

그럼 위에 말햇던걸 다시 말하면 파일의 크기가 12바이트가 아닌 18바이트여야 된다는 말이되죠

abex.l2c 파일을 열어서 18바이트를 만들어줍니다.

 

 

간단하게 123456789012345678 이라는 값을 넣고 저장을 했습니다.

이렇게 파일의 크기를 변경시킨 뒤 문제 파일을 실행시켜보면 ...

 

 

키파일을 제대로 찾았다고 메시지창이 뜨는걸 확인 할 수 있습니다.

그러면 심플스에서 출제한 문제의 답은 18Byte가 되겠내요

이렇게 이 문제는 끝입니다.

 

 

업무하면서 틈틈히 포스팅을 하려고하니 이 문제를 푼지 벌써 10일이 지났내요

최초 작성 날짜가 5월 16일인거 보니 ..

그 사이 크랙미를 9번까지 풀었습니다. (18번까진가 있던데 언제 다풀지..)

속도가 더디긴해도 한 문제 한 문제 포스팅할 예정입니다.

확실히 그냥 혼자 풀면 빠르긴한데 이렇게 글로 쓰니 좀 더 자세히 들여다볼 수 있으니 좋내요

다만 확실히 첫 번째 문제 풀 때 보다는 이해하고 설명할게 상대적으로 줄었다보니

분량은 적어졌내요 ~ 기억에 4번 문제가 VB이었던거 같은데 ..

제대로 포스팅할 수 있을지 모르겠내요 ..

어쨌든

끝.

' 2016년 이전 > CrackMe' 카테고리의 다른 글

abex CrackMe L02  (0) 2014.05.15
abex CrackMe L01  (2) 2014.05.07

뭐지 왜지 뭐지

며칠 전부터 블로그 접속자 수가 이상한데 ..

이렇게 많이 접속할리가 없는데 뭐지 왜지 뭐지

유입 경로도 다양하지도 않고 그대론데 왜 카운트는 저렇지 뭐지 뭘까

무섭게

' 2016년 이전 > 그냥' 카테고리의 다른 글

노트북 사고 ..  (2) 2014.07.01
  (0) 2014.06.19
리눅스 마스터 1급 접수 !  (0) 2014.03.21
정보보안 산업기사 시험 볼껄 그랬나  (0) 2014.03.19
결국 정보보안산업기사 접수 취소  (0) 2014.03.06

저번 포스팅 때 레벨 1 문제를 풀었었는데요..

그 후에 레벨 2 문제를 풀어봤습니다.

아니 사실 다른분들의 풀이를 몇 번이고 다시 보고 이제서야 눈에 조금 들어오는 정도내요

L01 처럼 눈에 확띄는 단어도 없었고 한 번도 손댄적이 없는 VB만들어져있더군요..

 

풀이를 몇 번이고 보고 포스팅을 하려고하니 결국 찾아서 봤던 풀이와 다를 것 없어질 것 같아서

그냥 링크를 납깁니다.

뭔가 글써놓으신 스타일이 제 머리에 쏙쏙 들어오는 스타일이라서 이해하기가 좀 더 편했습니다.

풀이를 보면서 궁금했던 점 위주로 포스팅을 하려고도 했지만

풀이를 보고 다시 또 보고 해서 눈에 들어온게 이번 주 초였고..

그 때 다 찾아봤더니 이제와서는 기억에 남는게 없더라구요..

다음부터는 풀이를 적당히 보고 빠르게 포스팅을 해야겠내요..

지금 기분은 마치 고등학생 시절에 수학 문제가 너무 안풀려서 풀이를 보고 이해를 했는데

정작 시험에 비슷한 문제 나왔을 때 기억이 안나는 기분이내요 ..

한 두번 정도 더 직접 보고 넘어가야겠습니다.

 

http://zzaps.tistory.com/121

(블로그 링크를 마음대로 가져온 점 죄송하구요. 원하시면 링크 내리겠습니다.)

 

이 블로그 외에도 abex crackme 검색하시면 많은 분들이 풀어놓은 풀이가 있으니 입맛에 맞게

찾아보시면 편하실 것 같습니다.

' 2016년 이전 > CrackMe' 카테고리의 다른 글

abex CrackMe 03  (0) 2014.05.16
abex CrackMe L01  (2) 2014.05.07

밑 빠진 독에 물 붓기

 

3.8

1.2.8

1.2.6

1.2.8

2.3.1(2.0 1.4 2.?)

* 3

' 2016년 이전 > Diary' 카테고리의 다른 글

  (0) 2014.07.31
2014. 04. 10.  (0) 2014.04.10
2014. 03. 10.  (0) 2014.03.10
2014. 02. 17.  (0) 2014.02.18
2014. 01. 22.  (0) 2014.01.22

심플스 Challenge에 있는 문제들을 하나씩 풀어보기로 했습니다.

물론 리버스 엔지니어링을 공부해본적이 전혀 없습니다..

친구가 하는 걸 한 두번 구경한 것 뿐이에요

풀이도 보고 검색도 하면서 차근차근 기초부터 배워나가야겠내요

이 글은 혼자서 검색도 하고 풀이도 보고 혼자 이해하기 위해서 쓰는 글입니다.

내용이 다소 먼 산으로 갔다가 돌아오기도 할 듯 하내요

 

제가 알기론 심플스가 예전엔 리버싱 관련 커뮤니티로 꽤 왕성하게 활동이 있었던걸로 알고 있는대요

아쉽게도 지금은 예전만큼의 활동은 안보이는듯 하더라구요

그래도 자료는 쉽게 구할 수 있으니 둘러보시면 좋을 듯 합니다.

http://simples.kr/Report

 

우선 심플스에 올라와있는 CrackMe L01 문제는 다음과 같습니다.

 

Down 표시는 기존 게시글에 Down 문자 바로 밑에 크랙미 파일 다운 링크가 있어서 있는겁니다.

어쨌든 문제를 보면 크랙미01의 주 핵심 API의 이름을 물어보고 있습니다.

예로 MessageBox를 적어줬내요. 저런식의 답을 원한다 이런거 아닐까 싶습니다.

그럼 CrackMe L01을 다운 받아봅니다.

 

CrackMe_L01.exe

 

이 파일이 의심스러우신분은 심플스에서 다운 받으시면 되겠습니다.

http://simples.kr/index.php?_filter=search&mid=Report&search_keyword=Crack&search_target=title&category=10705&document_srl=10828

 

다운 받아서 실행시켜보시면 정말 간단한 프로그램이라는 걸 알 수 있을껍니다.

 

            

 

대충 보면 하드를 시디롬으로 인식시켜달라는 말 같내요..

그냥 확인을 눌러버리면 '이건 시디롬이 아니야'라고 오류를 뱉고는 사라져버립니다.

 

그러면 사용법은 잘 모르지만 올리디버거를 이용해서 한 번 까(?)보겠습니다.

 

 

올리디버거로 크랙미 01을 열어보면 위 화면과 같은 내용들이 화면에 출력될 것입니다.

보면 3번 째 줄에 처음 실행시켰을 때 나왔던 메시지박스의 텍스트가 있내요

뭐가 뭔지 모르겠지만 그냥 눈으로 읽을 수 있는 것들을 쭉 내려가면서 읽어볼게요

6번 째 줄을 보면 RootPathName = "C:\" 라고 써져있습니다.

처음 봤던 메시지박스의 내용을 보고 대충 어림짐작해보면 아마 C드라이브를 시디롬으로 인식시켜야 되지 않나 싶내요.

바로 그 밑에는 빨간색으로 GetDriveTypeA 라고 쓰여져있습니다.

아직 뭔지 모르지만 일단 넘어가봅니다.

 

내려오다보면 두 번째 메시지박스의 텍스트가 있는 것을 알 수 있내요

근데 첫 번째 메시지박스의 출력내용과는 다르게 왼 쪽에 흰 줄로 묶여있는 걸 볼 수 있습니다.

묶여있는 제일 마지막 줄에는 빨간 글씨로 MessageBoxA라고 쓰여져있내요

아무래도 묶여져있는게 MessageBoxA라는 함수(표현이 맞나..)와 관련이 있어보입니다.

뭔지 궁금하니까 구글에 검색을 해봤습니다.

MessageBoxA는 Windows API 중 하나라고 하내요.

그렇다면 메시지창 하나를 띄우기 위해서 MessageBoxA라는 API를 사용한 걸 알 수 있습니다.

 

그 아래에 방금 전과 같이 MessageBoxA로 묶여있는 부분이 있는데 이 건 처음 실행했을 때 나오지 않았던 내용이내요

아마 C드라이브를 시디롬으로 인식시키는걸 성공 시키면 저 메시지가 출력되지 않을까 싶습니다.

그러고는 ExitProcess로 묶여있는 듯 보이내요.

바로 그 아래 흰 글씨로 GetDriveTypeA와 ExitProcess는 아직 어떤 역할을 하는지 모르니 일단 무시하도록 하죠.

 

일단 눈으로 볼 수 있고 읽을 수 있는 단어들만 둘러보면서 알 수 있었던 거는

API를 사용했다면 그 API가 사용하는 것들은 하나로 묶어서 보인다는 점.

그리고 C드라이브를 CD-ROM으로 인식시켜야될 것 같다는 점.

인식이 된다면 최초 실행시 못 봤던 메시지박스가 뜬다는 점.

GetDriveTypeA라는 API가 C드라이브를 가르키고 있다는 점.

대략적으로 이렇게 알 수 있겠내요.

이 4가지 단서들 중에 제가 느끼기에 중요해보이는 건 아무래도 GetDriveTypeA라는 API와 그에 관련해서

C드라이브를 시디롬으로 인식시켜야된다는게 중요하다고 느껴지내요.

여기서 유추를 해보면 C드라이브를 시디롬으로 인식시키려면 아무래도 무엇인가 비교를 해야하지 않을까 싶습니다.

아마 GetDriveTypeA라는 API를 사용하면 비교할 수 있는 어떠한 값이 나오지 않을까 싶습니다.

그럼 일단 GetDriveTypeA라는 API가 C드라이브를 가르키고 있다는게 무슨 의미인지 알아봐야겠내요.

구글링을 해보겠습니다...

...

꽤 검색을 해봤는데 한글로 글을 써놓으신 분이 거의 없더라구요..

한글로 된 책에서 찾아보지 않는 이상 정확하게 번역된 걸 찾기가 어렵지 않을까 하는 생각입니다..

그래서 그냥 MS공홈에서 제공하는 설명을 중요해보이는 리턴값에 대한 것만 캡쳐해왔습니다.

 

GetDriveTypeA라는 API를 사용했을 때 반환되는 값에 대한 내용인대요

예를 들어 API를 사용할 때 지정해준 드라이브가 뭔지 모를 때는 0의 값을 반환하내요.

영어끈이 짧아서 반환값 1에 대한건 무엇인지 해석이 안되내요..ㅠㅠ

나머지는 끈이 짧아도 충분히 알겠는데 말이죠 ..

어쨌든 이번 문제를 풀기 위해서 필요한건 C드라이브를 지정했을 때 반환값과

CD-ROM을 지정했을 때 반환값이 필요할 것 같습니다.

CD-ROM일 때는 반환값이 5라는 건 쉽게 알 수 있습니다.

그리고 C드라이브 같은 경우는 아무래도 이동식 디스크 같이 유동적인 드라이브가 아니라

고정적으로 물려있는 드라이브기 때문에 DRIVE_FIXED라는 반환값을 가지지 않을까 싶습니다.

물론 FIXED말고 다른 값을 가질만한게 없어보이긴 합니다.

그럼 이제 GetDriveTypeA라는 API를 사용했을 때 C:\나 D:\같은 고정적인 드라이브에 대한 반환값이 3이라는 것과

CD-ROM의 반환값이 5라는 것을 알았습니다.

아무래도 이 값들이 제일 중요한듯 한데 아마 문제의 답은 이 API가 아닐까 싶습니다.

 

이제 다시 OllyDbg로 돌아와봅니다.

반환값을 알았으니 이 반환값을 비교하는 걸 찾아야되겠내요

어찌 찾아야하나 .. 이리저리 찾다보니 이젠 .. 어셈블리어를 봐야되나보더군요..

아는게 하나도 없지만 눈치코치로 한 번 봐보겠습니다.

올리디버거 화면을 보면 왼쪽에 화면을 제일 크게 차지하고 있는 곳에 3번 째칸..음 사진으로 볼게요..

아까 썼던 이미지지만 보겠습니다.    ↑↑↑↑↑↑여기↑↑↑↑↑↑

이 화면에서 어셈블리어가 보이는 곳은 초록색 글자들이 있는 칸입니다.

영어 단어들과 요상한 숫자 조합들로 구성이 되어있는대요

잘 보면 익숙한 영 단어들도 있습니다.. 딱 봐서 제일 많이 보이는 PUSH도 보이구요

그 아래로 CALL이라는 단어도 보이내요

그 외 한 단어는 아니지만 축약어로 추청되는 INC, DEC, JE, JMP도 보이내요

아무래도 이 영 단어들이 어셈블리어일듯 합니다.

이 단어들이 정확히 무슨 기능을 하는지 모르니 검색을 해봤습니다.

 

우선 가장 많이 보이는 PUSH.

PUSH 인자1

push는 스택에 값을 저장하는 구문이라고 합니다.

여기서 또 스택이 뭔지 모르니 찾아봤는데요.

PUSH와 같이 정리가 되어있는 블로그가 있어서 참고 했습니다.

스택은 아주 간단하게 '데이터를 임시적으로 저장했다가 필요할 때 꺼내서 쓰는 임시기억장치'라고 하내요.

(참고 : http://csdit.tistory.com/16 )

대충은 이해되나 아직 정확하게 이해는 안되니 일단 넘어가겠습니다..

그리고 CALL.

CALL은 아무래도 단어 뜻 처럼 '부르다, 호출하다 등'의 의미와 똑같지 않나 싶지만 이 역시 검색해봤습니다.

검색을 하다보니 간단하게 기본적인 어셈블리어 구문에 대해 정리해놓은 블로그를 발견했내요

이 곳에 INC, DEC, JMP에 대한 글이 있으니 참고하시면 될 것 같습니다.

이 외에도 검색하면 많은 블로그들이 있으니 찾아보시면 좋을 듯 합니다.

(참고 : http://zerohz.tistory.com/61 )

아주아주 간단하게

CALL은 무엇인가를 호출할 때

INC는 값을 1씩 증가시키고자 할 때

DEC는 값을 1씩 감소시키고자 할 때

JMP는 특정 위치로 이동할 때

사용한다고 생각하시면 되겠습니다.

 

대략적으로 이 크랙미에서 사용하는 어셈블리어를 알아봤으니 다시 올리디버거를 찬찬히 보겠습니다.

어셈블리어가 나열되어있는 곳을 보면 PUSH로 시작합니다.

PUSH는 스택에 값을 저장하는 거니 뒤에 오는 값을 스택에 저장을 하겠구나.. 하고 넘어가겠습니다..

그러다 CALL을 만나는걸 보실 수 있습니다.

CALL 뒤를 보면 <JMP.&USER32.MessageBoxA>라고 써져있습니다.

자세히는 모르지만 아무래도 MessageBoxA라는 API를 호출하고 있는 것 같내요

F7을 이용해서 쭉 둘러봤지만 도통 아는게 없으니 뭔가 엄청난게 작동을 하는 것 처럼 보입니다.

하지만 단순히 MessageBoxA가 생성되고 실행되는 과정이겠죠

이렇게까지는 모르니 그냥 CALL로 MessageBoxA API를 불러온다는 것만 알고 넘어가겠습니다.

그 후 또 다시 한번 CALL이 있내요

그 뒤에는 <JMP.&KERNEL32.GetDriveTypeA>라고 써져있습니다.

이 문제의 핵심인 GetDriveTypeA라는 API를 호출하고 있는 듯 하내요.

GetDriveTypeA가 호출이 됬다면 반환값이 생길텐데 어디로 저장되는지는 아직 모르니 일단 쭉 내려가보겠습니다.

GetDriveTypeA를 호출하고 바로 다음 줄을 보면 INC ESI 라고 써져있습니다.

INC는 아까 적었듯이 값을 1씩 증가시켜주는 어셈블리어였습니다.

그렇다는건 ESI의 값을 1 증가 시키겠다는 거겠내요.

바로 그 밑에를 보면 DEC EAX라고 써있습니다.

DEC은 INC와 반대로 1씩 감소시키는 어셈블리어였죠

그렇다는건 EAX의 값을 1 감소 시키겠다는 의미일테구요.

그 아래로 ESI 와 EAX라는 단어가 계속해서 나오는데 이것에 대해서 또 검색을 해봤습니다.

 

찾아보니 EAX와 ESI는 범용레지스터에 속하는 녀석들이내요

잘 정리해놓은 블로그를 또 찾았습니다.

(참고 : http://blog.eairship.kr/186 )

여기서 필요한 EAX와 ESI에 대해 아주 간단하게 적어보자면

EAX - 산술, 논리 연산을 수행하고 함수의 반환값이 저장되는 레지스터

ESI - 데이터를 조작하거나 복사 할 때 Source 데이터의 주소가 저장되는 레지스터

참고한 블로그의 내용을 보고 이렇게 쓸 수 있겠내요.

여기서 EAX의 설명글 중에 '함수의 반환값을 저장'이라는 문장을 보면 왠지 GetDriveTypeA API의 반환값도

이 레지스터에 저장이 되지 않을까 생각이 듭니다.

일단 계속해서 어셈블리어로 되어있는 부분을 봐보겠습니다.

(새로 캡쳐한 이미지)

한 줄 한 줄 내려오다가 처음 INC와 DEC를 만난 이후에도 INC와 DEC가 한 두번 정도 더 사용되는 걸 볼 수 있내요

뭔가 계속 증가시키고 빼고 있내요

그러다가 CMP를 만나게 됩니다.

CMP는 아마 compare의 축약어인 것 같내요. 단어 의미 그대로 두 인자를 비교할 때 사용하는 어셈블리어라고 합니다.

이미지를 보면 CMP EAX, ESI 써있는게 보이는데요 EAX의 값과 ESI의 값을 비교하는 부분입니다.

위에서 예상했듯이 무엇인가를 비교하는 부분이 나왔내요

비교를 하고 서로 값이 다르거나 같다면 어떠한 행동을 취하겠구나 생각하고 다음 줄을 보겠습니다.

다음 줄을 보면 JE 라는 어셈블리어가 있내요

뭔지 찾아봤더니 JMP와 사촌격이랄까요

JMP는 지정된 곳으로 이동을 할 때 사용하지만 JE는 조건에 따라 이동을 하거나 안하거나 하는 어셈블리어라고 합니다.

보통적으로 CMP 같이 비교하는 명령어와 같이 사용하게 된다고 하내요.

그렇다는건 위에서 CMP로 비교한 결과에 따라 JE로 이동을 하게 되거나 그냥 지나치게 되겠내요

JE는 비교명령어를 사용했을 때 두 인자가 '같으면' 점프를 하는 명령어입니다.

JE 외에도 여러가지가 있는대요 그건 위에 어셈블리어를 검색하다가 찾은 블로그에 잘 정리가 되어있습니다.

어쩄든 JE 쪽에 써있는 걸 보면 'JE SHORT Crack_.0040103D'라고 쓰여져 있내요

조건이 맞으면 0040103D 주소로 이동하라는 것 같습니다. 앞에 크랙이라고 쓰여져있는건 파일명이내요.

0040103D가 어딘지 위 이미지로는 잘 안보이니 큰 이미지로 볼게요 

요 부분        ↑ 을 보면 가느다란 화살표가 JE가 이동하는 곳을 가르키고 있내요

가르키고 있는 곳을 보니 아무래도 CMP가 비교하는 값, 즉 EAX와 ESI의 값이 같으면

Error 메시지가 아닌 YEAH! 메시지를 볼 수 있겠내요.

어쨌든 JE 명령어 이후 아래부분은 맨 처음 봤던 MessageBoxA API부분과 동일하내요

마지막에 ExitProcess API만 빼고 말이죠. 이 API는 이름만 봐도 알 수 있다싶이 프로세스를 종료할 때 호출이 되는 API인 듯합니다.

 

이제 어셈블리어 부분도 다 봤습니다. 이 부분을 보면서 알 수 있었던 것은

CALL이라는 명령어가 GetDriveTypeA를 호출한다는 것.

산술이나 논리 연산, 혹은 함수의 반환값이 EAX 레지스터에 저장된다는 것.

INC와 DEC를 이용해서 값에 변화를 주고 있다는 것.

CMP로 비교한 EAX와 ESI의 값이 같으면 이 프로그램은 Error메시지가 아닌 다른 것을 출력 한다는 것.

 

그렇다면 이제 올리디버거에서 프로그램을 천천히 돌려보면서 EAX와 ESI의 값을 찾아보겠습니다.

올리디버거에서 레지스터 값이 표시되는 부분은                              ↓↓↓↓↓여기↓↓↓↓↓ 입니다. 

화살표로 표시해둔 부분을 보면 EAX와 ESI를 찾을 수 있습니다.

그 외에 ECX, EDX, EBX 등등 여러 레지스터들의 값들도 보이내요.

일단 프로그램을 처음 올리디버거로 불러왔을 때 레지스터 값을 보겠습니다.

EAX에는 770E494F 라는 .. 값이 들어가있고

ESI에는 00000000 이라는 아무것도 들어있지 않내요

이제 Alt + F9를 이용해서 천천히 한 줄 한 줄 실행시켜 보겠습니다.

MessageBoxA API까지 실행시켰습니다.

희안하게도 EAX에 값이 1이 들어갔습니다.(레지스터 부분에 빨간색 글씨들은 값이 이전과 다르면 빨간색으로 표시되내요)

ESI는 여전히 0이내요

이번에는 이번 문제의 핵심 API인  GetDriveTypeA를 실행시켜보겠습니다.

EAX의 값이 00000003으로 변했내요

EAX는 연산 결과값이나 함수의 반환값이 저장되는 거니 00000003 이라는건 GetDriveTypeA의 반환값이겠내요

API의 반환값이 3이면 DRIVE_FIXED의 반환값이내요.

유동적이지 않고 고정적으로 장착되어있는 드라이브의 반환값. API가 실행될 때 가르키고 있던게 C드라이브기 때문에

반환값 3을 EAX에 저장하게 된 것 같습니다.

ESI는 여전히 00000000이내요

다음 INC와 DEC들을 실행시켜보겠습니다.

우선 INC ESI가 위에 말했듯이 ESI의 값을 1 증가시키는지 확인해보겠습니다.

INC ESI를 지나니 정말 ESI의 값이 00000001로 변한 것을 확인 할 수 있내요

EAX는 00000003으로 유지되고 있구요

나머지 INC와 DEC들을 모두 실행시켜보겠습니다.

총 INC ESI가 3번, DEC EAX가 2번 실행됬으니

ESI의 값은 00000003이 되고 EAX의 값은 00000001이 된 것을 확인할 수 있습니다.

그리고 EAX와 ESI를 비교할 CMP와 JE를 실행시켜보겠습니다. 

비교 결과 EAX != ESI 이기 때문에 JE가 실행되지 않고 그냥 다음 줄로 넘어가버립니다.

이대로 계속 실행을 한다면 Error 메시지박스가 실행되게 되고 그 후 JMP를 만나면서 ExitProcces API가 실행됩니다.

Error메시지를 더이상 보고 싶지 않으니 JE가 실행되도록 값을 수정을 해야겠내요.

위에 CMP 명령어를 실행하기 직전에 EAX의 값과 ESI의 값을 같게 바꿔줘보겠습니다.

       

저는 그냥 GetDriveTypeA API의 CD-ROM 반환값인 5로 수정해줬습니다.

(아무래도 단순한 구조다보니 그냥 값만 같으면 상관없는 것 같더라구요)

다 바꾸고 Alt +F9로 한 줄 한 줄 볼 필요가 없으니 F9로 그냥 실행시켜 보겠습니다.

드디어 Error 메시지창이 아닌 YEAH! 메시지창이 출력이 됬내요.

이러면 이 크랙미는 끝입니다.

물론 EAX와 ESI의 값을 이렇게 직접적으로 수정하지 않고도 JE를 실행되게 할 수도 있습니다.

JE를 그냥 JMP로 바꾼다던지 INC나 DEC를 손 본다던지 하는 식으로 여러방법이 있습니다.

그 여러 방법을 다 적을 수도 없거니와 제가 다 알지도 못해서 여기까지 써야겠내요.

 

 

 

레벨 1 문제임에도 포스팅하려고 캡쳐하고 하다보니 시간이 몇 배는 더 걸리내요 ..

거기다 아무것도 모르는 바닥부터 천천히 검색하고 정리하면서 하려니 시간이 훅훅 지나가내요..

초반이니 기초적인 걸 찾아가면서, 적어가면서 한거라 내용도 꽤 길어져버렸내요

고작 레벨 1인데..

틀렸거나 추가되야할 내용이 있다면 댓글 달아주세요

아 그리고 .. 참고 URL 링크 ... 블로거분들 링크 걸어놓은게 싫으시거나 하시면 바로 말씀해주세요

 

 

참고 URL

http://simples.kr/Report - 심플스
http://csdit.tistory.com/16 - PUSH와 스택
http://zerohz.tistory.com/61 - 어셈블리어
http://blog.eairship.kr/186 - 범용레지스터

 

 

' 2016년 이전 > CrackMe' 카테고리의 다른 글

abex CrackMe 03  (0) 2014.05.16
abex CrackMe L02  (0) 2014.05.15

꽤 여러사람이 접근하는 서버나 PC에 매우 중요한 정보나 자료가 들어있는 드라이브가 있다면

관리자 입장에서는 상당히 신경이 쓰일겁니다.

유출되거나 없어지기라도 한다면...........

뿐만아니라 외장HDD나 USB 같은 이동식 저장소 같은 것들도 중요한 데이터가 들어있는데 분실의 위험이 항상 있으니...

 

그래서 인지 Windows에서는 원하는 드라이브를 암호화 시켜주는 기능을 제공해주고 있습니다.

바로 BitLocker라는 기능입니다.

여러 암호화 프로그램들이 있겠지만 기본적으로 WIndows에서 제공해주는거니 따로 파일을 구해서 설치하거나

라이센스 문제 때문에 골치 아플일도 없죠

다만 암호화 할 때 입력했던 비밀번호와 그 때 bitlocker 자체에서 제공해주는 복구Key 둘 다 분실한다면 ..

포맷하지 않는 이상 복구 할 방법이 없다고 하는거 같내요..

방법을 찾아보긴 할텐데 찾게 된다면 추가로 포스팅을 할 예정입니다

 

먼저 Bitlocker에 대한 자세한 정보는 제가 직접 적는거 보단 MS 공식홈에서 확인하시는게 더 정확하실듯 합니다.

http://windows.microsoft.com/ko-kr/windows7/products/features/bitlocker

 

사용방법은 상당히 간단합니다.

데스크탑용 Windows(아마 7 이후 버전들)이라면 따로 설치를 안해도 기본적으로 설치가 되어있는걸로 알고 있습니다.

설치가 됬는지 쉽게 확인하는 방법은 시작 버튼을 눌러서 아래 사진처럼 검색해보시면 쉽게 확인해보실 수 있습니다.

 

 

이런식으로 찾았을 때 없다면 따로 기능을 설치해줘야 합니다.

설치방법은 제어판 -> 프로그램 및 기능(혹은 프로그램 설치/제거)를 실행시켜서 왼편 메뉴에

'Windows 기능 켜기/끄기' 혹은 'Windows 기능 설치/제거'와 비슷한 메뉴를 눌러서 설치할 수 있습니다.

(제가 확인해본 바로는.. 데스크탑용 Windows는 따로 설치하는게 없고 기본적으로 설치가 되어 있는걸로 확인을 했습니다..)

Windows Server라면 기능추가 기능을 이용해서 설치가 가능합니다.

 

 

위 사진은 테스트를 한다고 미리 설치를 해둔 거구요. 설치하는 도중에 특별히 설정할 거는 없습니다.

이제 설치가 다 됬다면 암호화가 필요한 드라이브를 암호화 시켜주면 됩니다.

방법은 아까 말했듯이 간단합니다.

내 컴퓨터로 들어가서 원하는 드라이브 우클릭을 하면 아래와 같이 나옵니다.

 

우클릭시 'BitLocker 켜기'라는 메뉴가 없다면 제대로 설치가 안된 걸 수 있으니 다시 확인해보셔야 합니다.

이런식으로 해도 되고 'BitLocker 드라이브 암호화' 혹은 'BitLocker Drive Encryption'을 실행해서 해도 가능합니다.

실행하면 아래 사진과 같은 창이 뜨게 되는대요

 

\

 

내 컴퓨터에서 우클릭했을 때와 마찬가지로 'BitLocker 켜기'라는 메뉴가 있습니다.

원하는 드라이브 옆에 있는 BitLocker 켜기를 눌러주시면 경고창이 뜨는데 정말 진행하실거라면 그냥 '예'눌러 주시면 됩니다.

 

 

진행을 계속하면 드라이브를 암호화한 후 어떻게 인증을 할 것인지 선택하는 창이 나옵니다. 

 

 

사진처럼 암호를 사용하는 것은 설명할 것도 없이 드라이브를 사용할 때 입력해야하는 비밀번호를 설정하는 것이구요

스마트 카드를 사용하는 거는 간단하게 예를 들면 회사 사원증이나 통제구역같은 곳에 출입할 때 사용하는

카드같은 것을 이용해서 해제하는 방법입니다.

리더기가 있다면 테스트를 해볼텐데 리더기가 없어서 확인은 못해봤내요..

마지막에 자동 잠금해제는 말 그대로 이 컴퓨터에 해당 드라이브가 활성화 될 때 잠금을 자동으로 해제하는 옵션입니다.

다른 컴퓨터에서는 자동으로 해제가 되지 않겠죠

이 세 가지 옵션은 중복 선택가능합니다.

 

 

인증방법을 선택하고 설정한 뒤 다음으로 넘어가면 복구 키 저장방법에 대해 물어봅니다.

복구 키는 전 단계에서 설정한 인증방법으로 암호화를 해제할 수 없는 상황일 때 사용할 수 있는 키 입니다.

스마트 카드는 어떤식인지는 모르겠으나 암호로만 설정한 드라이브는 복구 키로 손 쉽게 접근이 가능했습니다.

간단히 말하면 두 번째 비밀번호인 샘입니다.

비밀번호(혹은 스마트카드)와 복구 키를 모두 분실한다면 해당 드라이브에 접근하는 방법은 .. 거의 없다고

생각하시면 됩니다. (포맷 밖에 답이 없다는 말이..)

 

 

포스팅용으로 캡쳐한거라 USB저장은 하지 않고 그냥 내 문서에 저장을 했습니다.

 

 

저장을 하고 다음을 누르면 암호화 시작이라는 버튼이 나옵니다.

누르면 암호화가 다 될 때까지 기다리기만 하면 드라이브 암호화는 끝입니다.

 

참고로 암호화하는데 시간이 상당히 오래 걸립니다..

용량에 따라 비례하는거 같은데 어느 커뮤니티에서 본게 800기가 가량 되는 드라이브 암호화하는데 이틀 걸렸다고...;;

테스트해보려고 임시로 생성한게 5GB 짜리 드라이브였는데 이것도 꽤 시간이 걸렸던거 같습니다.

20분 정도? 같은 방법으로 usb 16G도 해봤는데 대략 한 시간 정도 걸렸습니다.

 

어쨌든 암호화다 끝나면 해당 드라이브는 비밀번호를 모른다면 아무나 접근을 할 수가 없습니다.

중요한 자료가 있는 드라이브나 USB 같은 저장소를 암호화 하고 분실한다고 해도 쉽게 접근하지 못한다고 합니다.

usb를 암호화하고 다른 PC에 꼽아봤더니 바로 암호를 물어보는 창이 뜨는 걸보니 확실히 분실했을 때 정보유출 위험성이

낮아질거 같다는 생각은 들더군요..찾아보니 xp에서도 암호를 물어본다고 하내요.

정확하진 않은 정보인데 행여 접근이 가능하다 해도 CDRom 처럼 읽기만 되고 쓰기는 안된다고 하는거 같내요

(이러면 암호화하는 의미가 없죠 아마 읽기라는게 파일을 읽을 순 있는데 파일 내용을 암호화되서 볼 수 없지 않을까 싶내요)

 

마지막으로 BitLocker를 테스트해보면서 약간 취약하다고 느낀건

악의적으로 암호화 해놓은 드라이브 자료를 그냥 날려버린다고 할 때

그저 우클릭 -> 포맷으로 간단히 날릴 수 있더군요

포맷을 해버리면 자료도 날라가지만 암호화 해놓은 것도 바로 지워지더라구요

따로 설정하는게 있으려나 ..

게다가 앞서 적었듯이 인증방법과 복구 키를 잃어버린다면 .. .. ..

 

 

 

 

' 2016년 이전 > etc2' 카테고리의 다른 글

Windows Azure 관련  (0) 2014.01.22

틈틈히 웹고트 풀어보기로 결심!

3~4년만에 설치해봤는데 이거 하나도 모르겠내..

 

모르는건 힌트도 보고 검색도 하고 이리저리 고민도 하면서 풀어봐야겠내요

웹고트를 접속하게 되면 왼쪽 메뉴 중에 General이라는 메뉴가 있습니다.

눌러보면 Http Basics와 Http Splitting 이라고 있는데 Http basics는 Paros나 WebScarab 같은 툴을 이용해서

http request랑 response의 헤더를 구경해보라고 있는 페이지 같더라구요

가뿐하게 넘어가고 Http Splitting을 풀기 위해 눌러줍니다.

 

 

....... 영어를 해석해야하는 큰 문제가 생겼습니다..

대충 눈치껏 보면 이 레슨은 두 개의 스테이지로 되있고 첫 번째 스테이지는 HTTP Splitting 공격에 대한 거고

두 번째 스테이지는 Cache Poisoning에 대한 거 같내요.

다음 단락은 대충 캐리지 리턴(CR)이랑 라인 피드(LF)를 이용해서 200 OK를 강제로 보내라는 것 같내요

그러면 스테이지2가 열린다고... 스테이지2를 성공하면 메뉴에 초록색 체크가 생기고..

CR과 LF를 암복호화 할 때 아마 PHP Charset Encoder 라는 사이트가 유용할 거라고 하는 것 같내요

해석이 틀릴 수도 있지만 대강 이런 맥락인 듯 합니다.

 

우선 제대로된 기초가 없기 때문에 Http Splitting이 뭐고 Cache Poisoning이 뭔지 검색해봤습니다...

간단하게 적어보자면

 

Http Splitting : HTTP Response Splitting 공격은 웹 어플리케이션이 HTTP response가 분리될 수 있는 보안 취약점을 가지고 있다면

응답 메시지를 조작하여 Proxy 서버를 공격자의 의도대로 조작할 수 있는 공격 방식입니다. 공격받은 Proxy 서버를 사용하는

모든 사용자는 조작된 페이지를 보게 될 수 있습니다. (출처 : http://getroot.tistory.com/14)

간단히 말하면 HTTP Request를 보냈을 때 서버가 응답해주는 HTTP response의 내용을 입력값을 통해 인위적으로 조작할 수 있다는 것을 말하는 것 같습니다. 한 마디로 특정 값을 입력 했을 때 정상적인 응답 값을 두 개 혹은 그 이상 받아올 수 있는 거죠. 아무래도 사용자가 입력한 값을 제대로 검증하지 않으면 생기는 취약점인듯 합니다.

 

 

Cache Poisoning : 여러 사용자가 사용하는 웹캐시 또는 단일 사용자의 브라우저캐시에서 악의적인 목적으로 생성된 응답을 캐시하는 경우

 그 영향이확대됨. 프록시서버에서 흔히 볼 수 있는 것과 같이 공유 웹캐시에 응답이 캐시되는 경우, 해당 캐시의

 모든 사용자가  캐시항목이 없어질 때까지 악성콘텐트를 계속받음 (출처 : 구글링에서 구한 pdf 파일)

 정확하진 않지만 아마 Http Splitting 같은 공격을 통해 해당 서버의 캐시를 감염(?)시키면 감염된 캐시가 서버에서

 없어지지 않는 이상 그 서버를 사용하는 사용자들은 특정 페이지에 지속적으로 접근이 되게 되는 것 같내요.

 꽤 여러 종류가 존재하는 듯하고 기본적인 개념만 이해되고 아직은 정확한 개념을 잡질 못하겠내요

 문제를 풀어보면서 또 알아봐야겠내요.

이제 어느 정도 첫 스테이지의 의도가 파악이 되는 것 같내요

입력 값을 통해 CR과 LF를 이용해서 정상적인 http response 값을 두 개 이상 받아오게 하면 성공하지 않을까 싶습니다.

일단 정상적인 응답일 때 http 200 OK가 어떻게 생긴지 보면

HTTP/1.1 200 OK

이렇게 생겼다고 합니다. 문제를 대충 해석한거긴 하지만 문제에선 그저 이 메시지만 보내면 된다고 하니 그냥 바로 보내봤습니다.

 

 

역시나 아무런 반응이 없내요

아무래도 문제에서 알려주는 CR과 LF를 사용해야 할 듯한데 CR과 LF의 아주아주 대략적인 개념은 이렇습니다.

CR(Carriage Return) : 커서를 커서가 있는 행의 제일 앞으로 당긴다.

LF(Line-Feed) : 커서를 커서가 있는 행의 아랫줄로 옮긴다.

둘의 기능을 합치면 우리가 흔히 알고 있는 New Line(아마도 개행?)이라는 기능이 된다고 합니다.

뉴라인에 대한 표기가 OS별로 다르다고 하는데요 흔히 쓰는 Windows는 CR+LF를 사용하고

Like Unix 같은 경우는 LF만 사용해도 된다고 합니다. Mac의 경우에는 CR만 사용해도 되구요.

간추려서 써놨지만 이 내용을 좀 더 자세히 알고 싶으신 분은 https://kldp.org/node/46637 이 곳을 참고하시면 되겠습니다 ~

 

그럼 다시 스테이지로 돌아와서 CR과 LF를 포함시켜 입력을 해보겠습니다.

윈도우 환경이기 때문에 CRLF를 사용해야겠내요. 그렇다고 그냥 입력창에 CRLF를 입력하게 되면 아무일도 일어나지 않습니다.

이런 특수한 값을 웹 입력창에 넣으려면 아무래도 특수한 기호가 있어야겠내요

다행이 문제에 친절하게 그 값이 뭔지 알려주고 있습니다. CR은 %0d이고 LF는 %0a라고 써있내요

실제로 이 값들은 암복호화 사이트나 툴에서 그냥 엔터를 치고 urlencode해보면 나오는 값입니다.

근데 툴 마다 다른건지 모르겠지만 CR값을 좀처럼 구할 수는 없겠더라구요..보통은 LF로만 인식이 되는듯 합니다.

정말 값을 찾고 싶은데 잘 모르겠다 하시면 url인코딩이 아마 ASCII와 비슷한걸로 알고 있습니다.. 참고하시면 될듯 하내요

 

이제 CRLF의 암호화 값을 HTTP/1.1 200 OK와 같이 입력해보겠습니다.

 

%0d%0aHTTP/1.1 200 OK

라고 입력하고 Search!를 눌러줍니다.

 

그러면 위 사진같이 잘했다고 성공적인 공격이었다고 칭찬해줍니다.

스테이지1은 풀렸지만 단순히 CRLF만 추가해줬을 뿐인데 왜 클리어가 된건지 알아봤습니다.

 

이 스테이지의 기능을 간단히 보면 Search! 버튼을 눌렀을 때 입력칸에 있는 값을 redirect 시키는 기능이 있습니다.

.....음 테스트하는 도중에 알게 된건데 특별히 HTTP/1.1 200 OK라는 값을 안줘도 위 메시지가 나오내요..

이번 웹고트 버전 문제인지는 모르겠는데 CRLF가 있고 아무값이나 입력해도 스테이지1은 성공으로 인식을 합니다..
(현재 사용중인 웹 고트 버전은 5.4 버전입니다.)

어쨌든 Search!를 눌렀을 때 요청하는 http header와 응답받는 http header를 봐보겠습니다.

 

먼저 http request 값입니다.

Paros로 본거구요. 깜빡하고 아래부분을 안찍었는데 아래부분에는

 

language=%250d%250aHTTP%2F1.1+200+OK&SUBMIT=Search%21

라는 값이 보내지고 있습니다. 보면 아무래도 입력칸에서 입력받은 값은 language라는 값으로 보내지는 것 같내요

%250d와 %250a는 CRLF가 두 번 urlencoding 된 값입니다. 그 외 깨진거 같은 값들도 다 urlencoding 된 값이구요.

그리고 아래 사진에 보이는 값들을 보면..여러 정보들이 헤더를 통해 전달되는 걸 알 수가 있습니다.

포스팅하면서 필요한 부분만 빼고 헤더 값에 대한 자세한 내용은 따로 적지 않겠습니다. 검색하면 수두룩하게 나오는 내용이니..

 

다음은 http response 값입니다.

일단은 다른값들은 다 모른척하고 Location 값만 보겠습니다.

이동되는 주소를 보면 http request 때 보내졌던 값을 포함한 URL로 지정되어있습니다.

인코딩 되었던 값들이 다시 처음 입력했던 값으로 돌아온 걸 볼 수 있는데요

이 때 서버는 %0d%0a를 인식하게 됩니다.

그렇게 되면 아마 서버는 아래사진처럼 인식을 하게 될 겁니다.

이렇게 인식을 하게 되면 서버단에서는 HTTP/1.1 302와 HTTP/1.1 200 OK 두 값을 모두 정상적인 값으로 인식하고

클라이언트단에 응답값을 보내게 됩니다. 지금은 단순히 HTTP/1.1 200 OK라는 값만 보냈지만

몇 가지 헤더값을 추가하고 보내게 되면 해당페이지에 공격자가 원하는 내용을 출력시킬 수 있게됩니다.

다른 블로그를 보면 여러 답안들이 나오는데 그 답안들을 참고해서 설명을 조금 써볼게요

(출처 : http://getroot.tistory.com/14)

 

HTTP/1.1 302 Moved Temporarily

Date: Wed, 24 Dec 2003 15:26:41 GMT

Location: http:// victim.com /by_lang.jsp?lang=foobar

Content-Length: 0

 

HTTP/1.1 200 OK

Content-Type: text/html

Content-Length: 19

<html>Getroot</html>

기본적으로 php에서든 jsp에서든 redirect를 사용하면 HTTP 응답 코드를 301 혹은 302로 응답하게 됩니다.

그러니까 위 헤더 정보들은 소스상에서 redirect를 만난 후 서버가 보내준 http response 값이 되겠내요

Date는 뭐 그냥 시간이니 일단은 넘어가겠습니다.

그리고 Location.. 아까 파로스로 캡쳐한 사진에서 설명한 부분입니다.

사용자가 입력한 값이 소스코드 내용에 의해서 URL과 합쳐지고 그 합쳐진 URL이 써있는 부분입니다.

Location 바로 밑에 Content-Length라는 헤더 값이 있는대요

이 부분부터가 공격자가 악의적으로 입력한 값들입니다.

그러니까 최초 입력값을 넣을 때 foobar 뒤에는 %0d%0a가 있었던 것입니다.

여기서 궁금한게 Content-Length가 어떤 역할을 하길래 공격 코드에 등장한 걸까 하는 점이었습니다.

검색해보니 대략적으로 Content-Length라는 값에 의미는

HTTP Header 뒤에 오는 값의 크기(byte)라고 합니다.

그러니까 위 코드에서 보면 Content-Length: 0 이 의미하는 건 더 이상 출력할 내용이 없다. 정도 되겠내요

그 후 서버단은 아무것도 출력을 안하는 걸로 인식을 하고 있다가 HTTP/1.1 200 OK 라는 값을 만나고 당연히 그 값을 정상적으로 인식을 하게 됩니다.

그러면 이 때 부터는 공격자가 원하는데로 출력할 수 있는 권한을 갖게 되는거구요

위 코드에서는 단순히 'Getroot'라는 단어를 출력하는걸로 끝이지만 충분히 Getroot가 아닌 다른 악의적인 내용을 넣을 수도 있습니다.

웹고트의 문제인건지 모르겠으나 저는 저 코드뿐만아니라 검색해서 나오는 대부분의 답을 그대로 사용해보아도

Getroot 화면이 따로 뜨진 않더라구요.. PC문제인건지 웹고트 자체 문제인건지는 모르겠내요..

 

어쨌든 이렇게만 하면 단순한 http Splitting 공격을 성공하고 스테이지2가 열립니다.

 

대략적으로 메시지를 보면 ..

HTTP Splitting은 성공했고 .. 이제 공격대상 캐시를 감염시켜라라는 거 같내요

그 뒤 내용은 얼추 해석은 되는데 여기에 쓰자니 부끄러워 안쓰겠습니다........

 

어쨋든 스테이지2인 cache poisoning 공격을 성공해 클리어 하려면 Http splitting 공격으로 위조된 페이지가 기존에 저장되어

있던 캐시의 수정날짜 보다 이후여야하고 현재 시간보다도 미래의 날짜여야 합니다.

기존 캐시의 수정날짜를 알아내려면 Paros나 Webscarab 같은 툴을 사용해서 HTTP Header 값 중에

if-modified-since 라는 값을 찾으면 됩니다.

하지만 해당 문제를 그냥 해결하는게 목적이라면 굳이 그 시간을 알아내지 않아도 됩니다.

그냥 현재 시간보다 미래의 시간을 사용하면 되니까요..

if-modified-since 값이나 그냥 먼 미래의 시간을 이용해서 캐시 감염 공격을 하는 방법은 생각보다 간단했습니다.

우선 if-modified-since의 값을 찾아내보면 이런식으로 작성이 되어있습니다.

Fri, 12 Apr 2014 02:56:30 GMT

이 형식을 유지해야 정상적으로 인식이 되고 응답을 하게 됩니다.

그럼 이 값을 어떻게 이용하느냐는 아까 Http Splitting을 할 때 입력했던 값들 사이에 같이 넣고 URL인코딩을 해주면 됩니다.

단, 이름은 if-modified-since가 아니라 Last-Modified 로 입력을 해주면 됩니다.

 

foobar

Content-Length: 0

 

HTTP/1.1 200 OK

Content-Type: text/html

Last-Modified: Fri, 12 Apr 2099 02:56:30 GMT

Content-Length: 19

<html>Getroot</html>

 

날짜를 빨간 부분처럼 먼 미래로 설정하시면 됩니다.

위 값들을 그냥 URL 인코딩을 하게 되면 일반적으로 CRLF가 아닌 그냥 LF로만 인코딩이 되서 %0d%0a가 아닌 %0a로만 나옵니다.

 

foobar%0AContent-Length%3A+0%0A%0A%0AHTTP%2F1.1+200+OK%0AContent-Type%3A+text%2Fhtml%0ALast-Modified%3A+Fri%2C+12+Apr+2099+02%3A56%3A30+GMT%0AContent-Length%3A+19%0A%3Chtml%3EGetroot%3C%2Fhtml%3E

 

이 %0a를 메모장이나 다른 편집기들을 사용해서 %0d%0a로 변환해줍니다.

그러면 최종적으로 입력해야할 값이 나오게됩니다.

 

foobar%0d%0aContent-Length%3A+0%0d%0a%0d%0a%0d%0aHTTP%2F1.1+200+OK%0d%0aContent-Type%3A+text%2Fhtml%0d%0aLast-Modified%3A+Fri%2C+12+Apr+2099+02%3A56%3A30+GMT%0d%0aContent-Length%3A+19%0d%0a%3Chtml%3EGetroot%3C%2Fhtml%3E

 

이제 이 값을 스테이지2의 입력칸에 넣어주고 Search! 버튼을 눌러주면 이번 문제는 모두 해결이 됩니다.

 

 

이 한 문제 해결하고 일하면서 틈틈히 잘 모르는 내용들 하나하나 찾아보면서 하니 거의 이틀이라는 시간이 지났내요..

알고나면 생각보다 간단하고 쉬운 내용들인데 하나하나 찾아가면서 이해하고 풀어보고 하니 시간이 상당히 걸리내요

모르는 내용이 상당히 많았고 .. 잘못된 내용을 적으면 안되기에 이리저리 검색도 많이해보면서 했지만 중간중간 이상하게 설명된 부분이 있을 것 같내요

특히나 cache poisoning 부분은 글을 보면 알겠지만 내용이 많이 없습니다..

틀린부분이나 수정해야할 부분이 있다거나 추가되야할 내용이 있는거 같다 싶으시면 댓글 달아주세요 !

 

다음 문제는 언제 풀고 언제 글을 쓸지 ..

 

 

슬슬 더워지는듯

3.8

1.2.8

1.2.6

1.2.8

* 4

' 2016년 이전 > Diary' 카테고리의 다른 글

  (0) 2014.07.31
2014. 05. 12.  (0) 2014.05.12
2014. 03. 10.  (0) 2014.03.10
2014. 02. 17.  (0) 2014.02.18
2014. 01. 22.  (0) 2014.01.22

+ Recent posts