본문 바로가기

웹해킹/wargame.kr

php? c?

문제를 들어가면 다음과 같은 페이지가 나온다.

get source를 눌러 소스를 보았다.

<?php
 if (isset($_GET['view-source'])) {
     show_source(__FILE__);
    exit();
 }
 require("../lib.php"); // include for auth_code function.
 if(isset($_POST['d1']) && isset($_POST['d2'])){
  $input1=(int)$_POST['d1'];
  $input2=(int)$_POST['d2'];
  if(!is_file("/tmp/p7")){exec("gcc -o /tmp/p7 ./p7.c");}
  $result=exec("/tmp/p7 ".$input1);
  if($result!=1 && $result==$input2){echo auth_code("php? c?");}else{echo "try again!";}
 }else{echo ":p";}
?>
<style>
 table {background-color:#000; color:#fff;}
 td {background-color:#444;}
</style>
<hr />
 <center>
  <form method='post'>
  <table>
  <tr><td>D1:</td><td><input type='text' id="firstf" style="width:75px;" maxlength="9" name='d1'></td></tr>
  <tr><td>D2:</td><td><input type='text' style="width:75px;" name='d2'></td></tr>
  <tr><td colspan="2" style="text-align:center;"><input type='submit' value='try'></td></tr>
  </table>
  </form>
 <div><a href='?view-source'>get source</a></div>
 </center>
 <script>
  document.getElementById("firstf").focus();
 </script>

코드를 햇거하면 

 tmp/p7 파일이 존재하지 않으면 p7.c 파일을 컴파일 하여 p7이라는 파일을 만들고 첫번째 값을 p7이라는 실행파일에 집어넣고 실행한 값을 result라는 변수에 저장한 후 result 값이 1이 아니고 d1하고 d2 값이 동일하면 flag 값을 출력하고 그렇지 않으면 try again이라는 문구를 출력하라는 것이다.

 

이제 p7.c라는 코드를 확인해보자

http://wargame.kr:8080/php_c/p7.c

불러오는 중입니다...

다음과 같이 입력하면 p7.c 코드가 나온다.

 

#include <stdio.h>
#include <stdlib.h>
void nono();
int main(int argc,char **argv){
 int i;
 if(argc!=2){nono();}
 i=atoi(argv[1]);
 if(i<0){nono();}
 i=i+5;
 if(i>4){nono();}
 if(i<5){printf("%d",i);}
 return 0;
}
void nono(){
  printf("%d",1);
  exit(1);
}

다음 코드를 해석하면

#include <stdio.h>
#include <stdlib.h>
void nono();
int main(int argc,char **argv){
 int i;
 if(argc!=2){nono();}  // 값이 두개 들어가지 않으면nono 함수를 실행
 i=atoi(argv[1]); // 첫번째 값을 정수형으로 변환
 if(i<0){nono();} // 첫번째 값이 0보다 작으면 nono 함수 실행
 i=i+5;  
 if(i>4){nono();}  // i가 4보다 크면 nono 함수 실행
 if(i<5){printf("%d",i);} // i가 5보다 작으면  i 값을 return
 return 0;
}
void nono(){
  printf("%d",1);
  exit(1);
}

정말 말이 안된다. i가 0보다 크되 4보다 크고 5보다 작아야 한다.-> 오버플로우를 일으켜야 한다.

오버플로우란 범위 이상의 값을 집어 넣어서 생기는 오류이다.

코드를 보고 예를 설명하겠다.

#include <stdio.h>

int main(void) {
	int a = 2147483647 + 1;
	printf("%d",a);
	return 0;
}

int 형 같은 경우 범위가 -2,147,483,648 ~2,147,483.647이다. 

만약 최대범위인 214748367보다 큰 수가 들어가게 되면 어떻게 될까?

코드를 돌려보면

다음과 같이 -2147483648이 나온다. 

이처럼 버퍼 오버플로우를 이용해서 공격을 한다.

p7.c 코드를 보면 i는 0보다 커야 한다.

그러므로 양수형 범위의 값이 나와야한다.

오버플로우를 일으키는 값이 나와야 하기 때문에  d1에 2147483648이 들어가야 한다.

하지만 밑에 코드를 보면 i = i+5가 있다.

그렇기 때문에 d1에는 2147483648-5한 값인 2147483643이 들어가야한다.

그 후 result 값과 d2의 값이 같아야 하기 때문에 -2147483648이 들어가면 된다.

근데 여기서 값을 집어 넣을 때 문제가 되는 부분이 있다.

d1의 값이 10글자인데 9글자밖에 들어가지 않는다.

그렇기 때문에 F12를 눌러 d1 입력부분의 maxlength를 10글자 이상으로 늘려 준다.

다음과 같이 늘려 준 다음 d1에다가는 2147483643 d2에는 -2147483648를넣어준다.

그럼 

플래그 값이 나온다.

'웹해킹 > wargame.kr' 카테고리의 다른 글

web chatting  (0) 2020.02.05
php? c?  (0) 2019.11.07
img recovery  (0) 2019.10.24
type confusion  (0) 2019.10.22
tmitter  (0) 2019.08.12
md5 compare  (0) 2019.08.12