标签:获取 att toc char enc strcmp fmm sctf 规则
有三处反调,一处在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="")
go写的,没去符号,找到main_main,根据条件解flag就行了
感觉和上题都是看上去复杂,逻辑都很简单
第一个函数会获取一个输入,没具体分析,输个换行就过了
第二个函数会获取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="")
没什么难度的题,直接动调得到比对的数
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="")
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="")
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="")
一千多个文件,核心部分为
一共有三种,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
这题要拿服务器上的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
基本上就是个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;
}
upx,ppc指令
这题看得有点懵,还不能动调,好在加密简单,猜出来的
脱壳后查找字符串
这里有一串特殊的字符串,main中有strcmp,猜测是用来比较的字符串
加密属实没看明白,但加密部分似乎只有addi,所以猜测是加了某个值
字符串减2可得到CFI{i_love_powerpc,加个}就是flag
不过依然显示密码错误,不知为啥。。。
die看一下,
.rdata有壳,调试发现有反调,并且是在开头的smc里
懒得管,直接attach到程序,发现数据变了,出来了一个base64的密文
在die中还发现
aes,顺着这个角度很容易找到密钥和iv,解得flag
标签:获取 att toc char enc strcmp fmm sctf 规则
原文地址:https://www.cnblogs.com/harmonica11/p/13417084.html