-
level18war game Write up/ FTZ 2018. 11. 16. 01:35
++ 다시 라업을 적을거니 이 글은 참고만,,, 제대로 다시 풀 예정이다.!!! ++
--> 결국 다시 풀었다ㅑ,, 풀이 방법은 동일하나 코드 분석을 그나마 조금이라도 정확하게 해보고 싶었다,,ㅎㅎㅎ
음,, 이 문제는 코드만 분석하면 반은 할 수 있는 문제인 것 같다,,
++
2018.11.17
다시 코드를 보면 FD_xxx 라는 코드가 있는 것을 볼 수 가 있는데
fd는 File Descriptor 의 줄임말로 자신이 사용할 파일 또는 장치에 대한 고유 식별 값이며 리눅스에서 특정한 파일에 접근하기 위한 키라고 할 수 있다.
소켓 프로그래밍을 할 때 socket 함수를 사용하여 socket 을 생성하면 정수 값이 반환되는데 이 값이 fd 이다.
그리고 fd는 같은 프로그램 내에서 중복되지 않으므로 고유 값으로 사용가능하다.
파이프, FIFO, 소켓, 터미널, 디바이스, 일반파일 등 종류에 상관없이 모든 열려있는 파일을 참조할때 쓴다.
리눅스의 시스템 콜을 예로 하면, 파일을 여는 함수인 open() 함수의 반환 값이 바로 이 File Descriptor이다.
또, read() 함수, write() 함수, C언어의 gets() 함수의 인자로도 File Descriptor가 사용된다.
FD
OBJECT
POSIX name
stdio stream
0
standard input
STDIN_FILENO
stdin
1
standard ouput
STDOUT_FILENO
stdout
2
standard error
STDERR_FILENO
stderr
간단하게 소개를 하자면
fd _ set 구조체는 FD 를 저장하는 구조체이며 크기는128 byte이다.
fd_set 구조체에 2와 5의 fd 를 저장한다고 할 때, 2번 5번 비트가 1로 변경되며 값 저장은 fd_set 매크로를 사용한다.
위의 fds의 구조체의 배열을 출력해보면
0
1
0
0
1
0
0
~
~
가 된다,
fd_set fds; 와 같이 선언했을 때 값을 찍어보게 되면 쓰레기 값이 존재할 수 있다.
따라서 fd_zero($fds); 와 같이 초기화를 해야한다,
fd_zero는 fd_set으로 선언을 한 뒤 초기화를 해주는 함수라고 보면 된다.
select() 함수는 fd_set 구조체에 할당된 fd 의 이벤트가 발생하면 이를 감지하고 어떠한 fd 이벤트가 발생했는지 알려주는 역활을 한다.
예를 들어
위의 코드를 보자
fd event는 6미만의 값만 체크하며
6미만 2와 5 FD 이벤트가 발생했을 때만 select 함수가 발생한다.
만약에 5번 fd 이벤트가 발생하면 select 함수가 발생하고 찍어보면
0
0
0
0
1
0
0
~~~
와 같이 변경되는 것을 확인 할 수 있다.
즉 fd 이벤트가 발생하면 해당 이벤트만 남겨진 후 초기화 된다..
위는 select 함수의 원형이다..
++
아래는 문제 코드이다.
위는 read 함수의 원형이다.
다시 문제 풀이로 가면
일단 뭐 case 0x08 일 때 count가 1씩 감소한다.
그리고 check가 0xdeadbeef 이면 쉘을 딸 수 있다,
일단 check에 저 값을 넣으면 쉘을 딸수 있으니 넣어보자 했는데
스택구조를 생각하니 불필요한 생각이였다.
check 가 string[100]밑에 있기 때문이다... 그러므로 패스하고
다시 코드를 보자
case 0x08 일 때 count가 1씩 감소한다라고 ?? 그럼 0x08 을 쓰면
string[count]=x; 가 string[-1] ;; string[-2] .... 가 될 수 있다는 건데
그럼 string의 시작주소보다 각각 낮은 주소에 x값이 저장된다는 것이다.
그럼??? count 값을 적절하게 낮춰주면 check 변수에 넣을 수 있다는 뜻이 아닌가?
int 는 4byte이니
(python -c 'print "\x08"*4+"\xef\xbe\xad\xde"';cat) | ./attackme
짜자나ㅏㅏㅏㅏ!!!!!
이 문제는 그냥 코드 분석을 통해서만 풀었다,, 코드가 없었더라면 개고생 했을 것 같다...