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


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM