Wargame.kr 포스트는 이해한 내용과 복습을 위한 목적으로 작성되었습니다.

이번 포스트에서는 php? c? 문제에 대한 이해와 풀이를 진행해보도록 하겠습니다.


이번에는 생각보다 간단한 문제입니다.

문제를 풀어보도록 하겠습니다.




 

 문제 이해


문제는 다음과 같습니다.

문제를 보니 interger 타입에 대해 묻고 있습니다.

INT는 32bit로 되어 있으며, unsigned와 signed에 따라 값의 범위가 달라지게 됩니다.

먼저 문제로 들어가 소스를 살펴보았습니다.



<?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>


위의 코드는 나름 정리해서 보여지게 한 것입니다.

위의 코드에서는 일단 두 개의 입력 값을 post로 받습니다.


input1 값은 p7이라는 C 프로그램의 인자값으로 주어지고,

input2 값은 p7의 값의 결과값과 비교하는 값입니다.


여기서 나름 힌트라고 할 수 있는 것이 14번 라인입니다.

여기서 ./p7.c를 컴파일하여 사용한다는 것입니다.


즉, 현재 디렉토리에 p7.c라는 파일이 있다는 것입니다.

http://wargame.kr:8080/php_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);
}


위의 소스도 나름 보기 좋게 정리한 것입니다.

여기서 우리가 입력한 인자값(문자열 값)이 atoi함수를 통해 int로 변경되어 입력됩니다.

그리고 그 값이 각 if문을 통과할 때 정상적인 종료가 이루어집니다.


여기서는 int overflow를 이용하여야 합니다.




 

 문제 풀이


먼저 int overflow를 하기 전에 어떻게 integer overflow가 가능한지 알아보도록 합시다.


 

 integer overflow


integer 값은 unsigned일 때 -2147483648 ~ 2147483647 의 범위를 가지고 있습니다.

여기서 가장 큰 양수 값을 넣었을 때 위와 같은 비트 형태를 가지게 됩니다.

이때 만약 +1을 하게 되면 다음과 같이 값이 변하게 됩니다.


위의 값은 계산기이기 때문에 양수로 보이게 되지만, C의 unsigned int의 경우 다음과 같이 음수로 변하게 됩니다.


이러한 원리를 이용하여 integer overflow를 수행할 수 있습니다.



 

 문제 풀이


integer overflow 원리를 이용하여 다음과 같은 값을 넘겨주게 되면, 모든 if 값을 패스합니다.


+ Recent posts