写在前面
说句实在话,ISCC是真的男泵,甚至还有卖答案的
你看我,机械的课一大堆,还全都卡在一群人抢着上分的点
二三轮一滴血都抢不着,吐了,但是逆向除了250+好像都蛮简单,复现一下也可
RE
JustDoIt
复现加密代码即可
enc = [0x17, 0x44, 0x44, 0x0f, 0x5e, 0x0a, 8, 0x0a, 6, 0x5f, 8, 0x18, 0x57, 3, 0x1a, 0x69]
key = [0x49, 0x53, 0x43, 0x43]
for m in range(1, 16):
enc[m] = enc[m] ^ key[0]
enc[m] -= (key[m % 4]) % 5
enc[m] = enc[m] + (key[2] % 6) + key[3] / 6
enc[m] -= (key[1] / 7) + (key[0] % 7)
for k in range(1, 16):
enc[k] -= k
encfirst = enc[15]
for j in range(15, 0, -1):
enc[j] = enc[j-1]
enc[0] = encfirst
for i in range(16):
enc[i] += 61
for i in enc:
print(chr(int(i)), end='')
变形记
略微尝试控制流去混淆,结果脚本都没法用。
字符串倒序得到base编码,原代码中也有字符串倒序语段。
input = ""
for i in range(len(input)-1, -1, -1):
print(input[i], end='')
解出字符与少量数字的组合,随后在控制流中找到另一个处理段,似乎对数字有特殊处理:
继续溯流,发现Label10之下的主要逻辑就是对于字符判重,计数(最多为个位数),然后将数字作为字符加入新的字符串。
故重复字符会以数字形式出现在字符串中,我们只需要将base出来的数字字符转换成(对应长度-1)的上一个文字字符即可。
《狂彪》-1
复现代码逆推PRODUCT中的奇数位字节,但是无法获知完整数据,只能用于和区块链对拍
Input = 0x796B159ACD626B88
rec = []
res = []
while True:
a = Input % 16
if a > 9:
rec.append(a+55)
else:
rec.append(a+48)
Input = Input >> 4
if Input / 16 <= 0:
break
L = len(rec)
for i in range(L-1, -1, -1):
res.append(rec[i])
print(res)
a2 = ""
a3 = ""
a2 += chr(12 + res[0])
a2 += chr(41 + res[2])
a2 += chr(48 + res[4])
a2 += chr(59 + res[6])
a2 += chr(48 + res[8])
print(a2)
j = 0
for i in a2:
print("product[" + str(j) + "] is:", end='')
print(hex(ord(i)))
j += 2
尝试将参数寄存器值替换至无用常量地址并修改值,使之步过,但屡次尝试皆失败
区块链部分解码得到原料4-chloroisatin和产物Ammosamide B,答案已出一半
import binascii
get_material = [3618502788666131213697322783095070105623107215331596699973092047810475080552,1058281262647123517608537692030461]
get_product = [3618502788666131213697322783095070105623107215331596699973092053763329075037,20243186386546719615607895858]
get_process1 = [3618502788666131213697322783095070105623107215331596699973087511546546089720,433361630167923360325699769579027741]
get_process2 = [3618502788666131213697322783095070105622814690435284427132955240375693632919,196824228736615904168885915933727279070460387353732017605538823168085048193]
get_process3 = [3618502788666131213697322783095070105623107215331596699973090202942792293480,453865271870859686009512443558968829]
get_process4 = [3618502788666131213697322783095070105623107215331596684209297756428220130934,116134304106173752838290040472410775248544248888571]
get_process5 = [3618502788666131213697322783095070105623107215331596699973092055035805475938,390561785906337738142215509985376935339146674861]
get_process6 = [ 3618502788666131213697322783095070105623107215331596699972936515620310327981,27026365916588459387032368716299937596899]
get_process7 = [3618502788666131213697322783095070105623107215331596699973059256975961087183,7226332434034712610187648289138429597352157756401918758]
get_process8 = [3618502788666131213697322783095070105623107215331596699833216824194234956751,8681453366187219654156504602948270914253927580289092492730178164518]
get_process9 = [3618502788666131213697322783095070105623107215331596699973092052190822164855,24250728870542224371403440011046646025606]
get_process10 = [3618502788666131213697322783095070105623107215331596699973092053763091097225,719754857826395771474544964133992746787295598]
get_process11 = [- 32302999884,396961771411939227609093435139525806]
get_process12 = [3618502788666131213697322783095070105623107215331596697461277884358282559945,1898285677759758986129338258729885824979973151922206961853593519407470]
get_process13 = [3618502788666131213697322783095070105623107215331596699973091894050039732634,2485241126446291140247192738487640780058871]
get_process14 = [- 6837661594, 1592794196753852641372653235484033004844244927]
_list_1 = [get_material,get_product,get_process1,get_process2,get_process3,get_process4,get_process5,get_process6]
_list_2 = [get_process7,get_process8,get_process9,get_process10,get_process11,get_process12,get_process13,get_process14]
def parse_num_1(num): # 7之前乘两次,7包括7之后乘三次
print(hex(num[0]*num[0] + num[1]))
def parse_num_2(num): # 7之前乘两次,7包括7之后乘三次
print(hex(num[0]*num[0]*num[0] + num[1]))
for i in _list_1:
parse_num_1(i)
for i in _list_2:
parse_num_2(i)
后尝试patch步过所有工序和判断,结果输出错误怀疑需要完整工序才能转入正解而非暴力突破
后手动爆破得出工序为原料->3->8->12->产物,于是将初始化工序执行序列改成如下序列:
程序即可自行产出flag
奇门遁甲
控制流混淆,核心在switch case结构,破门顺序31284567
switch ( v41[0] )
{
case 1:
if ( v3 == 2 )
{
sub_401090();
goto LABEL_27;
}
break;
case 2:
if ( v3 == 3 )
{
sub_401010(v30);
goto LABEL_27;
}
break;
……
答案为所有显示数据拼接
Pull the Wool Over People’s Eyes
控制流混淆,主要逻辑如下,v35为输入:
strcpy((char *)v19, "ISCC{");
Srca = '}';
strcpy(v18, "YouAresoClever");
do //冒泡排序
{
for ( i = 0; i < v2; ++i )
{
v4 = v18[i + 1];
v5 = v18[i];
if ( v5 > v4 )
{
v18[i] = v4;
v18[i + 1] = v5;
}
}
--v2;
}
while ( v2 > -1 ); // get v19 ISCC{ACYeeeloorrsuv}
sub_401850(Src, v19, strlen((const char *)v19));
……
do
{
v4 = v35;
v5 = Src;
v7 = (char *)v4 + v3;
v8 = (char *)v5 + v3;
*((_BYTE *)v6 + v29) = *v8 ^ *v7;
v3 = v29 + 1;
v29 = v3;
}
while ( v3 < v28 );
……
结合下方二进制码,猜测应该是二进制转字节码再作处理,复现算法即可
key = b'ISCC{ACYeeeloorrsuv}'
ans = "0000000000000000000000000000000000000000011001110000110100110111000000110100000100001011000011010011100000111111010010100101110100010101000101000000011000000000"
for i in range(int(len(ans) / 8)):
print(chr(int(ans[i * 8:i * 8 + 8], 2) ^ key[i]), end="")
Convert
主要逻辑如下:
for ( i = 0; ; ++i )
{
result = i;
if ( i >= a3 )
break;
*(_BYTE *)(i + a1) -= 32;
*(_BYTE *)(i + a1) += i;
}
for ( j = 0; j < 4; ++j )
{
*(_BYTE *)(j + a1) += j ^ -(__int64)(*(char *)(j + a2) % 4);
*(_BYTE *)(j + a1 + 4) += *(char *)(j + a2) % 5;
*(_BYTE *)(j + a1 + 8) += 2 * j;
*(_BYTE *)(j + a1 + 12) += *(_BYTE *)(j + a1 + 4);
*(_BYTE *)(j + a1 + 16) += *(char *)(j + a2) / 5;
result = j + 1;
}
逆推复现即可
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
unsigned char flag[]={'(', '0', '$', '$', 'b', '(', '3', '@', '=', '8', '-', 22, -104, 80, 70, 85, 55, 74, 60, 70, 69, 24, 's'};
char key[] = "ISCC";
int len = strlen(flag);
for(int j=3; j>=0; j--){
flag[j+16] -= key[j]/5;
flag[j+12] -= flag[j+4];
flag[j+8] -= 2*j;
flag[j+4] -= key[j]%5;
flag[j] -= j ^ -(key[j]%4);
}
for(int i=0; i<len; ++i){
flag[i] += 32;
flag[i] -= i;
}
puts((char *)flag);
return 0;
}
Congraduations
自己骂自己环节:
不要急躁,姓■的,不要急躁
你管那上课鸟甚,边界条件看清楚再下手,憋急着撞南墙,别死钻牛角尖想着算法,细节,细节
qmemcpy(v5, "abcdefghijklmnopqrstuvwxyz", 26);
qmemcpy(v4, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 26);
for ( i = 0; ; ++i )
{
result = i + a1;
if ( !*(_BYTE *)(i + a1) )
break;
if ( *(char *)(i + a1) < 97 || *(char *)(i + a1) > 122 )
{
if ( *(char *)(i + a1) >= 65 && *(char *)(i + a1) <= 90 )
*(_BYTE *)(i + a1) = v4[(*(char *)(i + a1) - 65 + a2 + 26) % 26];
}
else
{
*(_BYTE *)(i + a1) = v5[(*(char *)(i + a1) - 97 + a2 + 26) % 26];
}
}
……
for ( i = 0; i < a3; ++i )
*(_BYTE *)(i + a1) -= 30;
for ( j = 0; j < a3 - 1; ++j )
*(_BYTE *)(j + a1) -= *(_BYTE *)(j + a1 + 1);
for ( k = 0; ; ++k )
{
result = a3 - 1;
if ( k >= a3 - 1 )
break;
*(_BYTE *)(k + a1) ^= *(_BYTE *)(a2 + 1);
}
局部凯撒密码+字符串变换,复现算法即可
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
char c[] = {-91,67,83,-108,68,66,-120,113,64,-87,-77,-89,2,-84,-71,-124,121,85,95,-97,115,-69,-68,23,-9,'_'};
char lower[] = "abcdefghijklmnopqrstuvwxyz";
char upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char key[] = "ISCC";
void transfer2(){
for(int i=0;i<26;i++){
if(c[i]>='A' && c[i]<='Z')
c[i] = upper[(c[i]-'A'+1)%26];
if(c[i]>='a' && c[i] <= 'z')
c[i] = lower[(c[i]-'a'+1)%26];
}
}
void transfer1(){
for (int k=0;k<25;k++)c[k] ^= key[1];
for (int j=25;j>=0;j--) c[j] += c[j+1];
for (int i=0;i<26;i++) c[i] += 30;
}
int main()
{
transfer1();
transfer2();
for(int i=0;i<26;i++)cout<<c[i];
return 0;
}
CrackMePlease
一点反调试没加,直接strcmp下断点,读取str1即可。
Misc
擂台-芝士雪豹
第一层:rar伪加密,指定加密位改成80即可
第二层为zip加密,考虑到内嵌压缩包过长可以使用已知明文攻击,但所有脚本使用攻击均显示加密方式未知。
archpr显示如下:
bkcrack显示如下:
PS F:\带学\CTF\bkcrack-1.5.0-win64\bkcrack-1.5.0-win64> .\bkcrack.exe -C .\zipfiles.zip -c 49183-secret.zip -p plain.txt -o 0x1e
bkcrack 1.5.0 - 2022-07-07
Zip error: entry "49183-secret.zip" is encrypted with an unsupported algorithm.
人生之路
图片要求用windows大图标模式查看,但这样一来,根据提示,在“脚下”的只剩下文件名+后缀,输入,成功解压。
得到flag.txt为:
eAbJtAbJeA bAtJeAtJbA bAtAeA bAtAeA bJtJbJeJtJeJ tAxJeJexJtbJteJ xAteJxeJtA bAxAeAtAteJ tAxJeAxJtA bAtJeAtJbA teJxeJtbJtJ teAxeAteAxeA bAtJeAtJbA bAtAeAxJbJ teAxbJxeJtbA xAteAxA tAeAxAbA xAteJxeJtA tAxJeJexJtbJteJ teAxeAteAxeA eJtJeJbJtJbJ
接下来纯脑洞,因为小写字符仅出现四个且间隔一定,猜想凯撒密码替换字符“wasd”为“xbte”,另外两个字符也可能是字符替换,但规律不明,预计代表线段长短。手动对齐凯撒密码,使用python matplotlib根据字符串画图:
import string
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator
c = "eAbJtAbJeA bAtJeAtJbA bAtAeA bAtAeA bJtJbJeJtJeJ tAxJeJexJtbJteJ xAteJxeJtA bAxAeAtAteJ tAxJeAxJtA bAtJeAtJbA teJxeJtbJtJ teAxeAteAxeA bAtJeAtJbA bAtAeAxJbJ teAxbJxeJtbA xAteAxA tAeAxAbA xAteJxeJtA tAxJeJexJtbJteJ teAxeAteAxeA eJtJeJbJtJbJ ".strip()
a = c.split(" ")
for i in range(len(a)):
a[i] = a[i].replace("x", "w")
a[i] = a[i].replace("b", "a")
a[i] = a[i].replace("t", "s")
a[i] = a[i].replace("e", "d")
stloc_x = 0
stloc_y = 30
for i in range(len(a)):
j = 0
if a[i][0] == 'w':
if a[i][j + 1] == 'A' or a[i][j + 2] == 'A':
stloc_y = 15
else:
stloc_y = 22.5
while j < len(a):
lenadd = 0
try:
if a[i][j+1] in string.ascii_uppercase:
if a[i][j+1] == 'J':
lenadd = 7.5
else:
lenadd = 15
if a[i][j] == 'w':
x = [stloc_x, stloc_x]
y = [stloc_y, stloc_y + lenadd]
plt.plot(x,y)
stloc_y += lenadd
if a[i][j] == 'a':
x = [stloc_x, stloc_x - lenadd]
y = [stloc_y, stloc_y]
plt.plot(x,y)
stloc_x -= lenadd
if a[i][j] == 's':
x = [stloc_x, stloc_x]
y = [stloc_y, stloc_y - lenadd]
plt.plot(x, y)
stloc_y -= lenadd
if a[i][j] == 'd':
x = [stloc_x, stloc_x + lenadd]
y = [stloc_y, stloc_y]
plt.plot(x, y)
stloc_x += lenadd
else:
if a[i][j+2] == 'J':
lenadd = 7.5
else:
lenadd = 15
org_x = stloc_x
org_y = stloc_y
if a[i][j] == 'w': stloc_y += lenadd
if a[i][j] == 'a': stloc_x -= lenadd
if a[i][j] == 's': stloc_y -= lenadd
if a[i][j] == 'd': stloc_x += lenadd
if a[i][j+1] == 'w': stloc_y += lenadd
if a[i][j+1] == 'a': stloc_x -= lenadd
if a[i][j+1] == 's': stloc_y -= lenadd
if a[i][j+1] == 'd': stloc_x += lenadd
x = [org_x, stloc_x]
y = [org_y, stloc_y]
plt.plot(x, y)
j += 1
except IndexError:
print("Err")
j += 2
stloc_x += 50
stloc_y = 30
x_major_locator = MultipleLocator(5)
ax = plt.gca()
ax.xaxis.set_major_locator(x_major_locator)
plt.show()