old.liveoverflow.com/binary_hacking/protostar/format1.html
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int target;
void vuln(char *string)
{
printf(string);
if(target) {
printf("you have modified the target :)\n");
}
}
int main(int argc, char **argv)
{
vuln(argv[1]);
}
이 문제는 format string 공격을 사용해야 한다. printf(string)는 FSB 취약점이 존재하는 코드로, printf("%s", string)으로 사용해야지 안전하다.
printf() 함수는 포맷 스트링 문자(%d, %x, %c 등)를 만나면 스택에 저장된 값을 출력한다. 또한 "%n" 포맷 인자를 만나면 이 포맷 인자의 순서에 해당하는 내용을 스택에서 pop하고, pop된 내용을 주소로 이용해 해당 주소에 지금까지 출력된 문자의 개수를 저장한다.
문제를 해결하기 앞서 target의 주소를 고정하기 위해서 aslr을 꺼준다.
echo 0 > /proc/sys/kernel/randomize_va_space
그 다음 objdump -t를 사용해서 target 변수의 주소 값을 찾아준다.
08049638
이제 임의의 문자(AAAA, XXXX등 아무 문자)를 입력하고, '%x' 포맷 스트링을 사용해서 16진수 값을 출력한다. 입력한 임의의 문자의 아스키 값을 찾아줘야 하므로 '%x'의 개수를 늘려가면서 찾아준다.
이때 문자가 한 블록 내에 들어가야 target의 주소를 pop할 때 정상적인 주소를 보낼 수 있다. 따라서 '%x.' 형식으로 출력하여 41414141(AAAA의 경우)가 한 블록 내에 들어가는 '%x'의 개수를 찾아준다.
다음으로는 target의 주소도 추가해서 매개변수로 넣어준다. 아스키값과 target의 주소가 제대로 출력되는지 확인한다. target의 위치는 129번째로, 이 위치를 기억해준다.
마지막으로 문제를 해결하기 위해 129번째 위치에 '%n'을 넣어준다. '%n'을 만나게 되면 이 순서에 해당하는 내용(target의 주소값, 8049638)을 스택에서 pop하고, 이 pop된 내용을 주소로 출력된 문자의 개수를 저장하게 된다. 즉, target의 값이 바뀌게 되어 문제가 해결된다.
이때 포맷 스트링의 개수(이 경우 130)에서 변하게 되면 주소가 한 블럭 안에 들어가지 않기 때문에 시그먼트 오류가 난다. 이를 주의해서 '%x'와 '%n'의 개수가 130개가 되도록 해준다.
./format1 $(python -c "print 'AAAA'+'\x38\x96\x04\x08'+'%x.'*128+'%n.'+'%x.'")
참고한 사이트
'CTF > 시스템' 카테고리의 다른 글
protostar format3 (0) | 2020.11.05 |
---|---|
protostar format2 (0) | 2020.11.05 |
protostar format0 (0) | 2020.11.01 |
protostar stack7 (0) | 2020.10.29 |
protostar stack6 (0) | 2020.10.29 |