index.php 에서 LFI 취약점이 발생해서 index.php의 코드를 가져와본다.

 

 

81~83번째 줄에서 LFI 취약점이 발생하고 .php가 붙어서 php 파일 말고는 실행할 수 없다.

위 코드가 index.php의 핵심이 되는 코드인데 debug_mode라는게 존재해서 이를 통해 변수들을 출력할 수 있다.

이외에도 주석으로 phpinfo.php라는 페이지가 있는데 phpinfo() 함수를 통해 웹서버의 서버 설정들을 보여준다.

설정중에 파일 업로드 기능이 활성화 되어있어 php 페이지로 파일을 던지면 http 통신이 끊어지기 전까지

/tmp 디렉토리에 php[A-Za-z0-9]{6}의 형식으로 난수파일명으로 변환되어 일시적으로 파일이 저장된다.

(실제로 테스트 해본결과 http 통신이 끊어져도 바로 삭제되지는 않는다.)

아무튼 좋다. 일단 서버에 파일업로드를 하는것 까지는 했는데 문제는 서버에 올라간 코드를 어떻게 실행할것이냐?

문제는 파일명이 난수화 되어 업로드 되서 확장자가 날라간다는 점이다.

이를 해결할 수 있는 방법은 zip wrapper를 통해 압축 파일을 서버에 올려 실행하는 방법이다.

zip wrapper는 압축파일 속에 있는 파일을 띄워주는 역할을 하는데

LFI 취약점이 존재하므로 zip안에 php 코드가 있다면 LFI 취약점을 통해 내가 올린 파일을 실행할 수 있다.

 

 

위 코드를 압축해서 zip 파일로 만든다.

 

 

이렇게 만든 파일을 index.php?page=index&debug_mode=31337로 던지면 debug_mode 덕분에

내가 던진 파일이 /tmp 디렉토리에 어떠한 난수값으로 업로드 되었는지 알 수 있고 include 하는 페이지가

index.php이기 때문에 무한루프에 빠져 http 통신이 안끊어지도록 하여 레이스컨디션 공격이 가능하다.

 

 

이러한 방식으로 무한루프에 빠져 변수정보가 계속 출력이 되고 여기서 /tmp/php5HKDtk라는 파일명을 뽑을수있다.

 

index.php?page=zip:///tmp/php5HKDtk%23a 로 접속을 시도하면 실질적으로

index.php?page=zip:///tmp/php5HKDtk#a.php 로 접속하는 꼴이 되어 /tmp/php5HKDtk 파일의 압축을 해제하여

그 안에 있는 a.php를 include 한다 라는 뜻이 된다.

이러한 방식으로 remote code execution을 성공했고 마찬가지 방식으로 flag를 출력할 수 있다.

 

'문제 > CTF' 카테고리의 다른 글

CODEGATE 2017 Prequals RamG-thunder  (0) 2017.02.15

pe 파일을 받았다. 실행시켜보니 암호화 문제같았다.


암호화 알고리즘을 분석해 복호화 알고리즘을 구현하는 문제같아서 IDA를 통해 분석해보았다.



string 검색을 통해보니 hidden menu라는 문자열이 보인다.



입력 받는 부분에서 4를 입력하면 hidden menu가 나온다. 암호화 알고리즘은 fake인가보다.



hidden menu를 보니 숨겨진 flag를 찾는 게임이라고 하고 각 단계별로 stage5까지 있다.



먼저 입력을 받으면 바이트 단위로 XOR연산을 하는데 


input값과 메모리의 값을 xor해서 특정 값(v40)과 비교를 한다. 




v50="MVYLXYUARJ" 이므로 v50과 메모리의값을 XOR연산하면 stage1의 input값이 나온다.


후에 안티디버깅을 해주는데 레지스터값 수정을통해 우회한다.



stage2는 특정 구조체에 있는 값을 비교해주는데 디버깅을 통해 메모리 값을 변조하여 우회하였다.



stage3는 레지스트리값을 검증하는데 HKEY_CURRENT_USER -> Hellow -> hellow_FishWorld 라는 레지스트리가 있기만 하면 통과된다.



regedit을 통해 레지스트리를 생성해주었다.



stage4는 stage2와 마찬가지로 특정 구조체의 값을 디버깅을 통해 변조하고 


간단한 안티디버깅을 하는데 마찬가지로 레지스터값을 변조해 우회하면 된다.



stage5는 stage1과 마찬가지로 input값을 특정값과 XOR연산해서 비교한다.



이번에는 v36과 비교를 하는데 간단한 코딩을 통해 stage5의 input값을 알아내었다.



최종적으로 v42에 위에서 단계별로 통과하며 얻은 값을 붙여주는데 v42를 통해 연산을 해서 c라는 파일을 생성한다.



파일 시그니쳐를 보니 png파일이다.




확장자를 붙여주니 올바르게 이미지가 보이고 클리어


'문제 > CTF' 카테고리의 다른 글

2016 WhiteHat Contest JB  (0) 2018.04.09


문제를 보니 4글자의 NAME을 찾는 문제이다.


정답이 여러개인거 같은데 그중 숫자 소문자 대문자 순으로 가장 먼저오는 문자열이 정답인가보다.






바로 디컴파일 해보니 각설하고 name과 serial을 받아 check_serial함수에 인자로 넘겨줘 함수가 return 1을 하면 옳다고 나온다.


check_serial함수만 보면 끝날듯하다.



C++ STL을 사용해 구현한 프로그램이라 분석하는데 꽤 오래 걸렸지만 


밑줄친 stringFindSecond함수를 두번 호출하고 값을 뺀 절대값이 5보다 같거나 작으면 된다. 


함수 끝마칠때 v28을 리턴해주는데 저 조건문으로만 들어가지 않으면 v28은 원래 선언된 1 그대로 리턴된다.


반복문은 총 12번 돌아가는데 serial값의 길이만큼 돌아가며 name 한자리씩 가지고와 serial을 생성한다.


먼저 StringFindSecond(char* a,char b)함수는 사용자 정의함수인데 a라는 문자열에서 b라는 문자가 2번째로 나오는 인덱스를 리턴해준다.


두번의 호출에서 v30이라는 문자열을 인자로 넣어주는데 string으로 밖혀있는 밑의 문자열이다.



v9는 내가 입력한 serial이고 v8은 내가 입력한 name이다.


반복문이 12번 돌기 때문에 내가 만약 name을 abcd로 입력했다면 AAABBBCCCDDD 그리고 입력한 serial값 12자리를 가지고 검증을 한다.


여기서 소문자로 입력한다면 v30의 문자열에서는 대문자로 변환되어 검색한다.


검증 루틴을 분석했으니 간단한 brute forcing을 이용한 코드를 짜보았다.




문제에서 숫자 소문자 대문자 순서중 가장 먼저 오는 문자열이 답이라고 했으므로 가장 먼저오는 문자열을 출력해보았다.







'문제 > CodeEngn_Advance' 카테고리의 다른 글

CodeEngn Advance 09  (0) 2017.01.10
CodeEngn Advance 08  (0) 2017.01.10
CodeEngn Advance 07  (0) 2017.01.10
CodeEngn Advance 06  (0) 2017.01.10
CodeEngn Advance 05  (0) 2017.01.10


프로그램을 실행하면 옳은값이 아닐경우 프로그램이 멈춘다. 


문제명도 그렇고 이부분에서 프로그램이 멈추는것도 그렇고 뭔가 어셈블리어를 매우 자세히 봐야할거 같은 느낌이 들었다.



입력을 받고 처리하는 부분도 IDA로 보았을때 역시나 완벽한 디컴파일이 안된다.



IDA 기능인 assembly graph view기능을 통해 보았을때 성공 메시지를 띄워주는 부분으로 점프하는 부분이 없다.


이부분에서 감이 매우안와서 고생했다.



GetDlgItemInt함수를 통해 input값을 eax에 저장하고 함수를 호출한후에 검증한다.


설명부터 하자면 401071의 점프하는 부분을NOP로 맞춰줘야 한다.


일단 내가 입력한 input값을 가지고 연산을 하는데 4084D0에 내가 입력한 값이 저장된다. 



그후에 0x601605C7을 더해주고 INC연산을 4번 더해서 총 4를 더해준다.



여기서 100401071이 중요하다. 


이 값은 위에서 점프하는 부분을 nop로 만들어주는데 밑의 사진이 바로 그부분이다.



eax에 있는 값을 두번 0x90으로 바꿔주는데 공교롭게도 위에서 우리가 nop로 바꿔줘야할 코드가 2byte이다.


즉 내가 입력한 값에 4를 더해주고 0x601605C7을 더한 값이 100401071이 되어야 하고 바이트 포인터이니까 401071이 된다.


이부분에 90을 두번 넣어주므로 결국에는 어셈블리어를 변경하는 셈이다.



식을통해 산출한 input값을 입력한후 디버깅하면 연산후에 점프하는 어셈블리어가 nop로 바뀌어있다.


입력을하면 성공메시지가 뜬다.




이문제는 문제를 만든사람도 참신하다는 생각이들고 이런식의 리버싱문제를 처음접해봐서 신기했다.


확실히 어셈블리어만 보고 리버싱하는 연습이 매우 필요할거같다.


'문제 > Reversing.kr' 카테고리의 다른 글

Reversing.kr ImagePrc  (0) 2017.01.23
Reversing.kr Ransomware  (0) 2017.01.21
Reversing.kr x64 Lotto  (0) 2016.10.06
Reversing.kr HateIntel  (0) 2016.10.05
Reversing.kr Music Player  (0) 2016.10.04


프로그램을 실행시키면 그림을 그릴수 있고 check 버튼을 누르면 wrong이라고 메시지 박스가 출력된다.



위 코드가 check버튼을 누르면 실행되는 코드이다.


코드를 보면 현재 내가그린 그림과 리소스에 저장된 이미지를 가져와 바이트단위로 비교를 한다.


즉 바이트 단위까지 맞춰서 그림을 똑같이 그려야 wrong 메시지가 뜨지 않을것이다.


상식적으로 불가능 하다.


첫번째로 생각한것은 리소스를 뽑아와 실제 이미지로 만들어서 보는것이고 


두번째로 생각한것은 메시지루프에서 윈도우메시지가 wm_create일때 즉 윈도우가 생성될때 아예 리소스를 띄워주는 것인데


두번째 방법은 함수조사도 해야하고 첫번째 방법이 더 빠를거 같아서 첫번째 방식을 택했다.



pe뷰어를 통해 보면 리소스 섹션에 비트맵형식의 리소스가 있다.


파일 시그니쳐 및 파일 헤더가 없기 때문에 긁어와도 온전한 이미지 파일이 되지 못할것이라 생각했다.



먼저 실행파일 내에 리소스를 뽑아주는 툴을 통해 리소스를 뽑았다.



헤더 없는 리소스가 뽑혔다.


이제 비트맵 이미지 헤더를 위에 만들어주면 될거같다.


비트맵 이미지 구조를 외우고 있는 사람은 없을것이기 때문에 나도 검색을 해봤다.


비트맵 이미지의 기본 구조는 크게 파일헤더,이미지헤더,컬러테이블,픽셀테이블로 이루어진다고 한다.



먼저 파일헤더이다.


빨강 : 파일 타입 정보


노랑 : 파일 크기


파랑 : 예약 영역(임시 할당)


검정 : 헤더의 크기



다음은 이미지 헤더이다.


빨강 : 이미지 헤더크기 (최소 40byte)


보라 : 이미지의 폭, 이미지의 높이


분홍 : 비트 플레인 수(현재 지원값은 1이라고 해서 1로 했음)


갈색 : 비트수 (16비트,24비트 비트맵 등이 있는데 구글 따라 24로 해봤음)


검정 : 압축타입(압축되지 않았음)


노랑 : 이미지 파일 크기(헤더크기를 제외한 순수 이미지 파일의 크기)


초록 : 무엇인지는 모르겠으나 0으로 채워져있음(마찬가지로 구글따라...)






위처럼 헤더를 생성해주고 비트맵 파일을 생성하면



하얀 바탕에 검정색 글씨가 쓰여있다.


이게 플래그인데 뭔지 공개하면 안되니까 빨강색으로 지워주었다.





'문제 > Reversing.kr' 카테고리의 다른 글

Reversing.kr Replace  (0) 2017.01.23
Reversing.kr Ransomware  (0) 2017.01.21
Reversing.kr x64 Lotto  (0) 2016.10.06
Reversing.kr HateIntel  (0) 2016.10.05
Reversing.kr Music Player  (0) 2016.10.04


파일을 받으니 실행파일과 영문모를 파일 그리고 readme가 나온다.




readme를 읽어보니 실행파일을 복호화 하라고 한다.


실행파일을 통해 암호화된 file을 복호화 하는 문제같다.



이 실행파일은 키값을 입력하면 키값에 따라 file이 바뀐다.



file을 Hxd로 열어봤는데 이렇게 나온다. 


readme에서 file은 pe파일 이라고 했으므로 파일 시작부분이 MZ로 바뀌도록 복호화 하면 될거같다.





upx패킹을 풀어주고 복호화 해주는 실행파일의 메인함수를 보니 리버싱을 방해하기위해 의미없는 명령어를 매우 많이 넣어놨다.


따라서 아이다로 디컴파일이 불가능하다.



string검색을 통해 실행이 시작되는 부분으로 왔다. 


key를 입력받는다.



그 후에 file을 오픈한다.


file을 오픈해서 file을 한 바이트씩 받아와 key값과 간단한 연산을 통해 file을 변경시킨다.


밑은 연산하는 부분이다.



연산하는 부분을 분석해 보니 xor연산 두번이 끝이다.......


분석결과 키값^file^0xFF=복호화될값 이렇게 된다.


즉 내가 abcd를 키값으로 설정했으면


file의 첫번째 바이트가 0xDE였으므로 


0x61^0xDE^0xFF=0x4D 가 되야한다.


이런식으로 키값을 찾아가다보면 파일의 크기만큼 키값을 받는건 절대 아닐거라 생각하고,


분명히 키값을 반복해서 사용할거라 생각해서 수작업으로 키값이 반복될때까지 키값을 추측해보았다.



이러한 문자열이 나오고 이 문자열들이 계속 반복되는것을 보아 letsplaychess라는 키값을 얻을수 있었다.


이 키값을 통해 file을 복호화 하니 실행파일로 우리가 자주보던 PE구조를 가진 파일의 형태를 볼수있었다. 




확장자 EXE를 추가해주고 파일을 실행해 보려 했으나 DLL이 없다면서 실행되지 않았다.


역시나 이 실행파일 역시 upx패킹이 되어있어 풀어주고 디컴파일을 해보니 Key를 출력해보는 부분을 찾았다.



'문제 > Reversing.kr' 카테고리의 다른 글

Reversing.kr Replace  (0) 2017.01.23
Reversing.kr ImagePrc  (0) 2017.01.23
Reversing.kr x64 Lotto  (0) 2016.10.06
Reversing.kr HateIntel  (0) 2016.10.05
Reversing.kr Music Player  (0) 2016.10.04


문제에서 password를 찾으라고 해놓고 이름을 알려주지 않아서 일단 아무값이나 넣고 디버깅 해보았다.



디버깅하다보니 DonaldDuck이라는 문자열과 내가 입력한 name을 비교한다


NameDonaldDuck이 되어야 한다.



이름을 다시 입력하고 패스워드를 1234로 입력해보니 1234 16진수 4d2 특정값을 비교한다


특정값을 10진수로 바꿔인증해보니 인증이 되지만 성공 메시지를 띄울라면 아예 프로그램을 패치해야 한다.


'문제 > CodeEngn_Advance' 카테고리의 다른 글

CodeEngn Advance 10  (0) 2017.02.07
CodeEngn Advance 08  (0) 2017.01.10
CodeEngn Advance 07  (0) 2017.01.10
CodeEngn Advance 06  (0) 2017.01.10
CodeEngn Advance 05  (0) 2017.01.10


디버깅을 해보려고 아무값이나 입력을했더니



3자리 이상이여야 한다고 해서 cmp eax,2로 실행파일을 바꿨다.



메시지 창을 띄우기전 조건을 보니 입력한 이름으로 만들어진 키값과 내가 입력한 키값을 비교해서 성공메시지를 띄울것인지를 판단한다.



중단점을 함수두개를 걸었는데 분석 결과 밑의 함수는 문자열을 비교해주는 함수이고 


위의 함수가 name을 가지고 키값을 만들어 주는 함수이다.



함수를 분석해보면 크게 4개의 연산 과정이 있는데



‘ – ‘ 문자를 기준으로 5자리로 나뉘는데 각 자리를 산출해내는 연산을 한다.


 3번째 연산 과정은 3,4번째 자리를 같이 산출하는 것 같다.


Name 2글자라고 했고 2번째 연산과정이 가장 짧고 코드로 구현하기 쉬워서 


2번째 연산 과정을 숫자와 알파벳 대소문자 조합을 통해 name을 만들어 코딩해봤다.




2번째 자리는 53b4가 되야하는데 연산을 해서 앞 4바이트를 가져오기 때문에 


53b4000~53b4999까지의 결과가 나오는 값들을 출력해 보았다.


출력된 값중 하나를 입력하니 인증이 되었다.

'문제 > CodeEngn_Advance' 카테고리의 다른 글

CodeEngn Advance 10  (0) 2017.02.07
CodeEngn Advance 09  (0) 2017.01.10
CodeEngn Advance 07  (0) 2017.01.10
CodeEngn Advance 06  (0) 2017.01.10
CodeEngn Advance 05  (0) 2017.01.10


실행파일을 peid로 열어보니 c#으로 만들어졌다는걸 알았고 c# 디컴파일러인 reflector를 사용해 분석했다.



먼저 실행시키면 키값은 16진수로 이루어져있다는 것을 알수있다


실제로 16진수 이외의 문자 (0~9,a~f가 아닌 문자)를 입력하면 프로그램에서 오류가 난다.



먼저 이과정에서 GetHashCode함수는 32bit 64bit 운영체제에서 다르게 해시값을 생성한다는 것을 알고 window7 32bit를 설치했다.


문제하나 풀라고 운영체제까지 설치했던 첫문제여서 기억이남는다.


코드를 보니 vxzzz함수를 통해 yreeeerwww의 값이 바뀌고 fsfsdf는 우리가 찾아야 하는 키값에 의해 결정된다.


vxzzz함수를 분석해보았다.



도저히 루틴을 복호화 할 자신이 없어서 브루트포싱 하기로 결정했다.



vxzzz함수에서 자료형이 unsigned int 이기 때문에 언더플로우가 발생해서 프로그램 실행시간이 매우 길어질것을 감안하여 


일단 언더플로우가 발생할 수는 아예 생략했다. 이부분은 내가 코딩을 잘 못해서 어쩔수 없는 선택이였다.


만약 언더플로우가 발생하는 수가 정답이였다면 못풀었을지도 모른다.


0~ffffffff까지 브루트포싱 했다.



거의 3억에 가까이 가서 키값이 나왔다. 두시간 돌렸다.


이부분도 내가 코딩을 잘 못해서 알고리즘을 공부했다면 좀더 효율적으로 프로그램을 짜 실행시간을 줄일수도 있었을지 모른다.



키값으로 나온 10진수를 16진수로 바꿔 인증하면 맞았다고 나온다.




//비쥬얼 스튜디오 없이 c#소스인 .cs파일을 컴파일 할 때


 C:\Windows\Microsoft.NET\Framework64\v4.0.30319 에 있는 csc.exe를 이용해 javac.exe로  자바 컴파일 하듯이 컴파일 하면됨.

'문제 > CodeEngn_Advance' 카테고리의 다른 글

CodeEngn Advance 09  (0) 2017.01.10
CodeEngn Advance 08  (0) 2017.01.10
CodeEngn Advance 06  (0) 2017.01.10
CodeEngn Advance 05  (0) 2017.01.10
CodeEngn Advance 04  (0) 2017.01.10


먼저 실행을 해보니 확인을 누르면 숫자가 올라가면서 특정 수에서 끝난다.


정답은 나왔지만 분석을 해보았다.



먼저 안티디버깅이 되어있어 eax 0으로 바꿔주며 풀었다.



이부분에서 숫자를 카운트 해준다 eax에는 원래 숫자가 카운트 되는 숫자가 있고 edi에는 1이 있다. 즉 하나씩 올려준다.



그리고 위에서 올린 값을 어느 변수(임시적으로 비교하기 위해 사용하는 변수로 생각됨)에 저장하여



어떤 헥스값과 비교한다. 조건에 부합하면 계속 진행되고 특정값 보다 커지면 프로그램이 종료된다.


어거지로 디버깅하며 카운트 되는 변수의 위치와 비교하는 부분을 찾았지만 프로그램 전체에 대한 루틴 분석은 아직 안된다


아는형이 일병 때 못 풀고 병장 때 다시 풀었다 했는데 나도 1년 뒤에 다시 봐야겠다


'문제 > CodeEngn_Advance' 카테고리의 다른 글

CodeEngn Advance 08  (0) 2017.01.10
CodeEngn Advance 07  (0) 2017.01.10
CodeEngn Advance 05  (0) 2017.01.10
CodeEngn Advance 04  (0) 2017.01.10
CodeEngn Advance 03  (0) 2017.01.10

+ Recent posts