zoukankan      html  css  js  c++  java
  • BUUCTF Re部分wp(八)

    [MRCTF2020]Shit

    有三处反调,一处在1640主函数中,一处在1270,直接patch就行

    还有一处不会给提示,但是不断循环,跳过方式为在获取输入函数后下个断点,运行程序后attach上(断点设在加密函数处断不下来,不知为啥)

    判断函数在

    1460中会对一些用到的数据进行修改,所以必须动调(不过分析1460也可以,可以跳过反调部分,就是太麻烦)

     逻辑很简单,这几个函数都有一些简单的花,不太影响

    c=[0x8C2C133A, 0x0F74CB3F6, 0x0FEDFA6F2, 0x0AB293E3B, 0x26CF8A2A, 0x88A1F279]
    k=[3, 16, 13, 4, 19, 11]
    t=[]
    p=[]
    t.append(0x8C2C133A)
    for i in range(5):
        t.append(c[i]^c[i+1])
    print(t)
    for i in range(6):
        temp=t[i]^(1<<k[i])
        temp=(temp>>16)&0xffff|(~(temp<<16)&0xffff0000)
        temp=((temp<<k[i])|(temp>>(32-k[i])))&0xffffffff
        p.append(str(hex(temp)))
    print(p)
    for i in p:
        print(chr(eval("0x"+i[2:4]))+chr(eval("0x"+i[4:6]))+chr(eval("0x"+i[6:8]))+chr(eval("0x"+i[8:10])),end="")

    [b01lers2020]chugga_chugga

    go写的,没去符号,找到main_main,根据条件解flag就行了

    [b01lers2020]little_engine

    感觉和上题都是看上去复杂,逻辑都很简单

    第一个函数会获取一个输入,没具体分析,输个换行就过了

    第二个函数会获取flag,第三个函数进行加密,最后一个比对

     

    这里比对的数据地址每次加4

    a="E1 E6 D0 4A F2 C3 7E AA E6 FC 42 B2 F2 B5 01 B4 EC 7D 39 20 EF C0 4E 13 C8 2F 67 AA 95 79 6B F5 F2 06 41 79 D8 35 F9 C8 8E DE 88 51 AC 4C F0 81 E0 F4 EE 14 AD F1 25 BD 82 7C 62 30 A5 F8 80 2B 79 85 2A F8 6E 5A AE CB 18 3A A2 D0 09 C5 8C 5D 3D 34 6B F9 3B 72 4B 0E 4A C3 71 53 E1 E9 07 BB C1 1A E7 07 8F 1B 75 74 B9 8E 5D 2E C2 F6 17 3B 52 ED D7 BD 5E E9 76 63 72 E2 EA 89 51 D7 4F 34 DC 39 D5 58 92 D9 D2 D2 AA 69 F1 BF 90 76 E1 9C 39 0D 0C B3 40 06 48 DA 27 D5 1E B8 4A 94 4C 98 C4 8A 68 A8 97 5E 64 F9 C0 58 F7 02 72 8D 3B 88 18 14 EC 8F 42 70 0C 0B 96 66 22 8E F7 58 01 2E C5 DC 4B C0 71 F4 DA E6 3D 73 88 7D E4 91 1F 75 90 70 D6 0C A7 09 7C F2 5A 4E A1 09 0C 51 3C BA A8 64 38 2D 8C 00 88 E3 6F EA 77 90 74 39 AA 56 F1 A8 6E 80 CA 3D 9E 69 A4 69 48 F2 0A 2C F7 33 17 0F 5C F2 8A E5 2F 55 A5 9F 8B 65 54 76 E0 64 EE 9D 9B 2D 9B 5F 72 7F 3B D9 DF 05 69 F0 9F F0 A3 8C E6 CD EF B4 BC 44 54 3E E3 44"
    a=a.split()
    c=[]
    for i in range(len(a)):
    if i%4==0:
    c.append(a[i])
    print(chr(0xe1^0x91),end="")
    t=0x91
    for i in range(1,len(c)):
    t=(t+i-1)%0xff
    print(chr(eval("0x"+c[i])^t),end="")

    [watevrCTF 2019]esreveR

    没什么难度的题,直接动调得到比对的数

    a=[0x77,0x61,0x74,0x65,0x76,0x72,0x7b,0x65,0x73,0x72,0x65,0x76,0x65,0x72,0x5f,0x72,0x65,0x76,0x65,0x72,0x73,0x65,0x64,0x5f,0x79,0x6f,0x75,0x74,0x75,0x62,0x65,0x2e,0x63,0x6f,0x6d,0x2f,0x77,0x61,0x74,0x63,0x68,0x3f,0x76,0x3d,0x49,0x38,0x69,0x6a,0x62,0x34,0x5a,0x65,0x65,0x35,0x45]
    for i in a:
        print(chr(i),end="")

    [XMAN2018排位赛]Dragon Quest

    64位elf,有混淆,主要分析的函数是

    使用f5,里面有大量

    这些y和x在bss段上,调试发现并没有写的操作,一直为默认的0

    所以这些判断第一条小于10则为真,大于等于10为假

    汇编发现主要用了eax,ecx,edx,esi,和edi,还有的用了其他的寄存器,但因为判断是有多个&&和||,所以不用全改也行

    addr=
    while(addr<):
        next_addr = NextHead(addr)
        if "eax, ds:" in GetDisasm(addr):
            PatchByte(addr,0xb8)
            PatchByte(addr+1,0x00)
            PatchByte(addr+2,0x00)
            PatchByte(addr+3,0x00)
            PatchByte(addr+4,0x00)
            PatchByte(addr+5,0x90)
            PatchByte(addr+6,0x90)
        if "ecx, ds:" in GetDisasm(addr):
            PatchByte(addr,0xb9)
            PatchByte(addr+1,0x00)
            PatchByte(addr+2,0x00)
            PatchByte(addr+3,0x00)
            PatchByte(addr+4,0x00)
            PatchByte(addr+5,0x90)
            PatchByte(addr+6,0x90)
        if "edx, ds:" in GetDisasm(addr):
            PatchByte(addr,0xba)
            PatchByte(addr+1,0x00)
            PatchByte(addr+2,0x00)
            PatchByte(addr+3,0x00)
            PatchByte(addr+4,0x00)
            PatchByte(addr+5,0x90)
            PatchByte(addr+6,0x90)
        if "esi, ds:" in GetDisasm(addr):
            PatchByte(addr,0xbe)
            PatchByte(addr+1,0x00)
            PatchByte(addr+2,0x00)
            PatchByte(addr+3,0x00)
            PatchByte(addr+4,0x00)
            PatchByte(addr+5,0x90)
            PatchByte(addr+6,0x90)
        if "edi, ds:" in GetDisasm(addr):
            PatchByte(addr,0xbf)
            PatchByte(addr+1,0x00)
            PatchByte(addr+2,0x00)
            PatchByte(addr+3,0x00)
            PatchByte(addr+4,0x00)
            PatchByte(addr+5,0x90)
            PatchByte(addr+6,0x90)
        addr = next_addr

    去完混淆逻辑就好懂多了

    a=[100,214,266,369,417,527,622,733,847,942,1054,1106,1222,1336,1441,1540,1589,1686,1796,1891,1996,2112,2165,2260,2336,2412,2498,2575]
    print(chr(a[0]),end="")
    for i in range(1,len(a)):
        print(chr(a[i]-a[i-1]),end="")
                                    

    [QCTF2018]babyre

    rust逆向,拖进ida,主函数是main函数上面的那个函数

    看着挺复杂,有很多感觉没啥用的函数,不过程序本身逻辑比较简单,可以靠动调解决

    将32长度的字符串每四个一组交换位置,之后减去一个值,在将高位和低位转换

    c="DA D8 3D 4C E3 63 97 3D  C1 91 97 0E E3 5C 8D 7E 5B 91 6F FE DB D0 17 FE D3 21 99 4B 73 D0 AB FE"
    c=c.split()
    for i in range(len(c)):
        c[i]=eval("0x"+c[i])
    flag=[]
    for i in range(len(c)):
        if i%4==0:
            t=(c[i]<<5|c[i]>>3)&0xff
            t-=7
        if i%4==1:
            t=(c[i]>>6|c[i]<<2)&0xff
            t-=0x12
        if i%4==2:
            t=(c[i]<<7|c[i]>>1)&0xff
            t-=0x58
        if i%4==3:
            t=(c[i]<<4|c[i]>>4)&0xff
            t-=0x81
        flag.append(t)
    for i in range(len(flag)):
        if i%4==0:
            print(chr(flag[i+1]),end="")
        if i%4==1:
            print(chr(flag[i+2]),end="")
        if i%4==2:
            print(chr(flag[i-2]),end="")
        if i%4==3:
            print(chr(flag[i-1]),end="")

    [CFI-CTF 2018]Automated Reversing

    一千多个文件,核心部分为

    一共有三种,sub,add,xor

    for i in range(1009):
        File = 'binary'+str(i)
        with open(File,"rb") as f:
            f=f.read()
        if ord(f[0xca])==0xf2:
            print chr(ord(f[0xcb])^ord(f[0xce])&0xff),
        if ord(f[0xca])==0xea:
            print chr(ord(f[0xcb])+ord(f[0xce])&0xff),
        if ord(f[0xca])==0xc2:
            print chr(ord(f[0xce])-ord(f[0xcb])&0xff),

    这题我做过一道类似的,可以看看DASCTF五月线上赛 BScript blink

    [watevrCTF 2019]sabataD

    这题要拿服务器上的flag,先看给的程序

      

    程序逻辑比较简单,输入字符进行转换后分为三份

    其中/home/ctf/flag.txt是个过滤,可以用/home/ctf//flag.txt代替

    根据规则可构造

    Fw/eahttocemhve r/f-cratodfmm/ i/fnfi_ll_ae_g _.w_ti_xt_th__ __i__n__d__e__x

    转换方式可测试得到替换表,之后构造输入

    a="Fw/eahttocemhve r/f-cratodfmm/ i/fnfi_ll_ae_g _.w_ti_xt_th__ __i__n__d__e__x"
    t1="nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM"
    t2="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    for i in a:
        if i=="_" or i=="/" or i=="-" or i=="." or i==" ":
            print(i,end="")
        else:
            print(t2[t1.index(i)],end="")
    Sj/rnuggbprzuir e/s-pengbqszz/ v/sasv_yy_nr_t _.j_gv_kg_gu__ __v__a__q__r__k

    [GUET-CTF2019]encrypt

    基本上就是个rc4

    #include<stdio.h>
    #include<string.h>
    
    int s[256];
    char cmp[]="Z`TzzTrD|fQP[_VVL|yneURyUmFklVJgLasJroZpHRxIUlH\vZE=";
    char flag[50];
    int key[]={16,32,48,48,32,32,16,64};
    
    void sub_4006B6(){
        for(int i=0;i<=255;i++){
            s[i] = i;
        }
        int v4 = 0,v7 = 0,v8 = 0;
        for ( int j = 0; j <= 255; ++j ){
                v4 =s[j];
                v7 = (v7 + v4 + key[v8%8]) % 256;
                s[j] = s[v7];
                s[v7] = v4;
            v8++;
          }    
    }
    
    void sub_4007DB(int len){
        int i=0,t=0,j=0,temp=0;
        for(int k=0;k<len;k++){
            i=(i+1)%256;
                    j=(j+s[i])%256;
                    temp=s[i];
                    s[i]=s[j];
                    s[j]=temp;
                    t=(s[i]+s[j])%256;
                    flag[k]=s[t]^flag[k];
            }
    }
    
    void sub_4008FA(){
        int j=0;
        for(int i=0;i<strlen(cmp);i++)
            cmp[i] -= 61;
        for(int i=0;i<strlen(cmp);i++){
            if(i%4==0){
                flag[j]=cmp[i]<<2|cmp[i+1]>>4;
                j++;
            }
            else if(i%4==1){
                flag[j]=cmp[i]<<4|cmp[i+1]>>2;
                j++;
            }
            else if(i%4==2){
                flag[j]=cmp[i]<<6|cmp[i+1];
                j++;
            }
        }
    }
    
    int main(void){
        sub_4006B6();
        sub_4008FA();
        sub_4007DB(strlen(flag));
        printf("%s",flag);
        return 0;
    }

    [CFI-CTF 2018]powerPacked

    upx,ppc指令

    这题看得有点懵,还不能动调,好在加密简单,猜出来的

    脱壳后查找字符串

    这里有一串特殊的字符串,main中有strcmp,猜测是用来比较的字符串

    加密属实没看明白,但加密部分似乎只有addi,所以猜测是加了某个值

    字符串减2可得到CFI{i_love_powerpc,加个}就是flag

    不过依然显示密码错误,不知为啥。。。

    [SCTF2019]creakme

    die看一下,

     .rdata有壳,调试发现有反调,并且是在开头的smc里

    懒得管,直接attach到程序,发现数据变了,出来了一个base64的密文

    在die中还发现

    aes,顺着这个角度很容易找到密钥和iv,解得flag

  • 相关阅读:
    剑指offer--12.不用加减乘除做加法
    剑指offer--11.数组中出现次数超过一半的数字
    剑指offer--10.最小的K个数
    剑指offer--9.字符串的排列
    剑指offer--8.调整数组顺序使奇数位于偶数前面
    剑指offer-7.旋转数组的最小数字
    剑指offer--6.数值的整数次方
    剑指offer--5.变态跳台阶
    剑指offer--4.斐波那契数列
    剑指offer--3.用两个栈实现队列
  • 原文地址:https://www.cnblogs.com/harmonica11/p/13417084.html
Copyright © 2011-2022 走看看