ssh로 서버에 접속해서 문제를 풀어야 한다.
우선 접속해서 살펴본다.
analysis
서버가 좀 느리다.
flag를 읽어야하고 passcode 프로그램에는 set uid가 걸려있다.
C 코드를 분석하고 쉘을 따면 될 것 같다.
프로그램 실행 먼저 해보면 이렇게 뜬다.
passcode 코드는 생각보다 짧다.
#include <stdio.h>
#include <stdlib.h>
void login(){
int passcode1;
int passcode2;
printf("enter passcode1 : ");
scanf("%d", passcode1);
fflush(stdin);
// ha! mommy told me that 32bit is vulnerable to bruteforcing :)
printf("enter passcode2 : ");
scanf("%d", passcode2);
printf("checking...\n");
if(passcode1==338150 && passcode2==13371337){
printf("Login OK!\n");
system("/bin/cat flag");
}
else{
printf("Login Failed!\n");
exit(0);
}
}
void welcome(){
char name[100];
printf("enter you name : ");
scanf("%100s", name);
printf("Welcome %s!\n", name);
}
int main(){
printf("Toddler's Secure Login System 1.0 beta.\n");
welcome();
login();
// something after login...
printf("Now I can safely trust you that you have credential :)\n");
return 0;
}
조건에 나와있듯이, flag를 얻기 위해서 passcode1 이 338150이고, passcode2가 13371337인 조건을 만족해야한다.
이상한 점은 scanf를 받을 때, &를 빼먹었다는 것이다. 여기서는 scanf에서 &를 실수로 빼면 어떤 취약점이 발생할 수 있는지 보여주는 것 같다.
scanf는 본래 주소에 값을 입력하는 것이지만, 이렇게 되면 passcode1, passscode2가 가지는 값을 주소로 하여 거기에 입력할 것이다.
따라서 passcode1, 2에 원하는 주소를 넣을 수 있으면 좋다. 변수가 초기화되어있지 않기 때문에 그 전 함수에서 주소를 지정할 수 있다.
passcode1 변수는 ebp-0x10
passcode2는 ebp-0xc이다.
이전 함수에서 ebp-0x70부터 100만큼 덮으므로 0x64만큼 덮으니까. ebp-0x10은 덮는다. ebp-0xc~ebp-0x8은 못 덮으니까 passcode2는 이후 고려할 사항이 된다.
이걸로 일단 원하는 주소에 원하는 값을 덮을 수 있다.
그러면 여기엔 RELRO가 걸려있지 않으니 got overwrite를 통해 flag를 출력하는 주소로 바꿀 수 있을 것이다.
solution
그 전에 조건을 어떻게 맞춰보려고 했었는데 이건 불가능하다. python code 작성도 안되고.. 페이크로 주석을 붙여놓은 것 같다.. ㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠ
gdb를 잘 쓸 줄 모르니 plt 코드를 보고 got를 구해본다.
got 주소는 0x804a004이다.
여기에
원래는 모든 분기를 통과해야 넘어갈 수 있는 0x080485d7를 넣어준다.
된다.
하. 주석때매 got overwrite 쉽게 생각하지 못한게 후회된다.
있는 그대로 문제를 봐야겠다.