【NSSCTF】刷题记录——[SWPUCTF 2021 新生赛]系列(REVERSE篇)

新手小白,开启CTF刷题之路(持续更新)

此处主要在NSSCTF平台(NSSCTF | 在线CTF平台)上开展刷题

[SWPUCTF 2021 新生赛]简简单单的逻辑

下载附件,内容如下:

flag = 'xxxxxxxxxxxxxxxxxx'
list = [47, 138, 127, 57, 117, 188, 51, 143, 17, 84, 42, 135, 76, 105, 28, 169, 25]
result = ''
for i in range(len(list)):
    key = (list[i]>>4)+((list[i] & 0xf)<<4)
    result += str(hex(ord(flag[i])^key))[2:].zfill(2)
print(result)
# result=bcfba4d0038d48bd4b00f82796d393dfec

麻……真的麻,年轻时没有好好学习,后果就是一把年纪重新捡起这些玩意看到程序就头皮发麻……慢慢分析开始吧唉

len()函数用于返回字符串、列表、字典、元组等长度,语法为【len(str)】,其中str是要计算的字符串、列表、字典、元组等。

range()函数是Python中的内置函数,用于生成一系列连续的整数,一般用于for循环体中。

在本题中,len(list)的结果是17,嵌套了range()函数后,结果是(0,17)

接下来for循环里设置了一个key变量,变量从list数组中取值,从第0位即47开始,分别使list数组中各个数值执行x向右移4位(相当于除以16并取整)的结果与同一个值的按位与运算(使用符号为&,即如果前后两个值相应的二进制位都为1,则该位的结果值为1;否则为0)的结果左移4位(相当于乘以16)的结果相加,获得的key数组为(242,168,247,147,87,51,248,17,69,162,120,196,150,193,154,145)。

result使用了ord、hex、zfill、str函数,用途分别为:

ord()用来返回对应字符的ascii码

hex()用于将10进制整数转换成16进制,以字符串形式表示

str.zfill(width)根据width长度对str进行切片

对for循环进行分析,转换和注释如下:

flag = 'xxxxxxxxxxxxxxxxxx'
list = [47, 138, 127, 57, 117, 188, 51, 143, 17, 84, 42, 135, 76, 105, 28, 169, 25]
result = ''
for i in range(len(list)):
    m=list[i]
    print(m)
    print('__m__')

    j=m>>4           #  >>按位右移,左移n位相当于除以2的n次方,此处相当于除以16并取整
    print(j)
    print('__j__')

    n=list[i] & 0xf  #  &按位与,如果两个相应的二进制位都为1,则该位的结果值为1;否则为0。本题中所取值的转化为二进制后与0xF(即1111,高位自动补0)进行按位“与”运算,取得值再转换为十进制表示
    print(n)
    print('__n__')
    
    k=n<<4           #  <<按位左移,左移n位相当于乘以2的n次方,此处相当于乘以16
    print(k)
    print('__k__')
    
    key = j+k
    print(key)
    print('__key__')
    
    i+=1
#    result += str(hex(ord(flag[i])^key))[2:].zfill(2)

# result=bcfba4d0038d48bd4b00f82796d393dfec

得出key值

47	__m__	2	__j__	15	__n__	240	__k__	242	__key__
138	__m__	8	__j__	10	__n__	160	__k__	168	__key__
127	__m__	7	__j__	15	__n__	240	__k__	247	__key__
57	__m__	3	__j__	9	__n__	144	__k__	147	__key__
117	__m__	7	__j__	5	__n__	80	__k__	87	__key__
188	__m__	11	__j__	12	__n__	192	__k__	203	__key__
51	__m__	3	__j__	3	__n__	48	__k__	51	__key__
143	__m__	8	__j__	15	__n__	240	__k__	248	__key__
17	__m__	1	__j__	1	__n__	16	__k__	17	__key__
84	__m__	5	__j__	4	__n__	64	__k__	69	__key__
42	__m__	2	__j__	10	__n__	160	__k__	162	__key__
135	__m__	8	__j__	7	__n__	112	__k__	120	__key__
76	__m__	4	__j__	12	__n__	192	__k__	196	__key__
105	__m__	6	__j__	9	__n__	144	__k__	150	__key__
28	__m__	1	__j__	12	__n__	192	__k__	193	__key__
169	__m__	10	__j__	9	__n__	144	__k__	154	__key__
25	__m__	1	__j__	9	__n__	144	__k__	145	__key__

再对原题给的py程序转换如下:

flag = 'xxxxxxxxxxxxxxxxxx'
list = [47, 138, 127, 57, 117, 188, 51, 143, 17, 84, 42, 135, 76, 105, 28, 169, 25]
result = ''
for i in range(len(list)):
    key = (list[i]>>4)+((list[i] & 0xf)<<4)
    a=flag[i]
    print(i)
    print('__i__')
    print(key)
    print('__key__')
    print(a)
    print('__a__')
    b=ord(a)
    print(b)
    print('__b__')
    c=b^key    # ^按位异或操作
    print(c)
    print('__c__')
    d=hex(c)
    print(d)
    print('__d__')
    result += str(d)[2:].zfill(2)
    print(result)
    # result=bcfba4d0038d48bd4b00f82796d393dfec

#    result += str(hex(ord(flag[i])^key))[2:].zfill(2)

给出的结果如下:

0	__i__	242	__key__	x	__a__	120	__b__	138	__c__	0x8a	__d__	8a		
1	__i__	168	__key__	x	__a__	120	__b__	208	__c__	0xd0	__d__	8ad0
2	__i__	247	__key__	x	__a__	120	__b__	143	__c__	0x8f	__d__	8ad08f	
3	__i__	147	__key__	x	__a__	120	__b__	235	__c__	0xeb	__d__	8ad08feb
4	__i__	87	__key__	x	__a__	120	__b__	47	__c__	0x2f	__d__	8ad08feb2f
5	__i__	203	__key__	x	__a__	120	__b__	179	__c__	0xb3	__d__	8ad08feb2fb3	
6	__i__	51	__key__	x	__a__	120	__b__	75	__c__	0x4b	__d__	8ad08feb2fb34b
7	__i__	248	__key__	x	__a__	120	__b__	128	__c__	0x80	__d__	8ad08feb2fb34b80
8	__i__	17	__key__	x	__a__	120	__b__	105	__c__	0x69	__d__	8ad08feb2fb34b8069
9	__i__	69	__key__	x	__a__	120	__b__	61	__c__	0x3d	__d__	8ad08feb2fb34b80693d
10	__i__	162	__key__	x	__a__	120	__b__	218	__c__	0xda	__d__	8ad08feb2fb34b80693dda
11	__i__	120	__key__	x	__a__	120	__b__	0	__c__	0x0    __d__	8ad08feb2fb34b80693dda00
12	__i__	196	__key__	x	__a__	120	__b__	188	__c__	0xbc	__d__	8ad08feb2fb34b80693dda00bc
13	__i__	150	__key__	x	__a__	120	__b__	238	__c__	0xee	__d__	8ad08feb2fb34b80693dda00bcee
14	__i__	193	__key__	x	__a__	120	__b__	185	__c__	0xb9	__d__	8ad08feb2fb34b80693dda00bceeb9
15	__i__	154	__key__	x	__a__	120	__b__	226	__c__	0xe2	__d__	8ad08feb2fb34b80693dda00bceeb9e2
16	__i__	145	__key__	x	__a__	120	__b__	233	__c__	0xe9	__d__	8ad08feb2fb34b80693dda00bceeb9e2e9	

这样一看好像清晰了点儿,那么,接下来要干的活就是一层层的解题了。

首先,回忆下异或,异或的基本性质就是若 a^b=c,那么 c^b=a,所以在这里,key的值可以直接用。要做的,就是把题目给的result值按照两位一切,加上0x构造十六进制值,使用int函数转换为十进制,与key异或运算后取得ASCII值,然后使用chr函数转换为字符串,最终构造flag,代码如下:

result = 'bcfba4d0038d48bd4b00f82796d393dfec'
list = [47, 138, 127, 57, 117, 188, 51, 143, 17, 84, 42, 135, 76, 105, 28, 169, 25]
flag = ''
for i in range(len(list)):
    key = (list[i]>>4)+((list[i] & 0xf)<<4)

    a=result[i*2]+result[i*2+1]  #对result字符串切片并取值
    print(a)
    print('__a__')

    b='0x'+a  #构造十六进制
    print(b)
    print('__b__')

    c=int(b,16)  #将十六进制转化为十进制
    print(c)
    print('__c__')

    d=c^key  #异或运算取得ASCII值
    print(d)
    print('__d__')

    e=chr(d)  #将取得的ASCII值转换为字符串
    print(e)
    print('__e__')

    flag+=str(e)  #构造flag字符串
    print(flag)

最终flag get

——20230815——

[SWPUCTF 2021 新生赛]简简单单的解密

题目源码如下:

import base64,urllib.parse
key = "HereIsFlagggg"
flag = "xxxxxxxxxxxxxxxxxxx"

s_box = list(range(256))
j = 0
for i in range(256):
    j = (j + s_box[i] + ord(key[i % len(key)])) % 256
    s_box[i], s_box[j] = s_box[j], s_box[i]
res = []
i = j = 0
for s in flag:
    i = (i + 1) % 256
    j = (j + s_box[i]) % 256
    s_box[i], s_box[j] = s_box[j], s_box[i]
    t = (s_box[i] + s_box[j]) % 256
    k = s_box[t]
    res.append(chr(ord(s) ^ k))
cipher = "".join(res)
crypt = (str(base64.b64encode(cipher.encode('utf-8')), 'utf-8'))
enc = str(base64.b64decode(crypt),'utf-8')
enc = urllib.parse.quote(enc)
print(enc)
# enc = %C2%A6n%C2%87Y%1Ag%3F%C2%A01.%C2%9C%C3%B7%C3%8A%02%C3%80%C2%92W%C3%8C%C3%BA

注释一波:

import base64,urllib.parse
key = "HereIsFlagggg"
flag = "xxxxxxxxxxxxxxxxxxx"

s_box = list(range(256))  #  range()生成一系列连续的整数,list()生成列表,此处即生成一个0-255的数组

j = 0
for i in range(256):
    a=len(key)
    b=i%a # %——取模,返回除法的余数
    c=key[b]
    d=ord(c)
    print('a=',a,'b=',b,'c=',c,'d=',d,'j=',j)
    print('__i=',i,'__')

    j = (j + s_box[i] + d) % 256  
    print('__j=',j,'__')
    s_box[i], s_box[j] = s_box[j], s_box[i]
    print('s_box[',i,']=',s_box[i],'s_box[',j,']=',s_box[j])
    print('=====================================')
res = []
print('res=',res)
print('————————for loop 1————————')

i = j = 0 #i,j值归零
for s in flag:
    i = (i + 1) % 256
    j = (j + s_box[i]) % 256
    s_box[i], s_box[j] = s_box[j], s_box[i]
    t = (s_box[i] + s_box[j]) % 256
    k = s_box[t]
    print('new_for_i=',i,'new_for_j=',j,'s_box[i]=',s_box[i],'s_box[j]=',s_box[j],'t=',t,'k=s_box[t]=',k)
    m=ord(s)
    print('m=',m)
    n=m^k
    print('n=',n)
    o=chr(n)
    print('chr(n)=',o)

    p=res.append(o) #append是属于python中的一个函数,它主要是用来在列表末尾添加新的对象。语法格式为list.append(obj)
    print('res.append(chr(n)=',p)
print('————————for loop 2————————')
cipher = "".join(res) 
# join(): 连接字符串数组。将字符串、元组、列表中的元素以指定的字符(分隔符)连接生成一个新的字符串
# 语法: 'sep'.join(seq),参数说明:sep:分隔符。可以为空,seq:要连接的元素序列、字符串、元组、字典
# 上面的语法即:以sep作为分隔符,将seq所有的元素合并成一个新的字符串
# 返回值:返回一个以分隔符sep连接各个元素后生成的字符串

# 以utf-8对cipher编码
#   encode()用来给字符串使用指定的编码格式来编码字符串。与之对应的是解码decode()。
#   语法:str.encode(encoding='UTF-8',errors='strict')
#   参数说明:str:需要操作的字符串,也就是需要编码的字符串。
#       encoding -- 需要使用的编码,如: UTF-8、GBK等。
#       errors -- 设置不同错误的处理方案。默认为 'strict',意为编码错误引起一个UnicodeError。 
#       其他可能得值有'backslashreplace', 'replace'、'ignore', 'xmlcharrefreplace', 以及通过 codecs.register_error() 注册的任何值。

crypt = (str
         (base64.b64encode
          (cipher.encode('utf-8'))
          , 'utf-8')
           ) #将cipyer以utf-8编码后以base64加密,并转换成字符串类型
print('crypt=',crypt)
enc = str(base64.b64decode(crypt),'utf-8')#对上述结果进行base64解密

enc = urllib.parse.quote(enc)#把生成的cipher中的非ASCII字符转换成%**形式
print(enc)
# enc = %C2%A6n%C2%87Y%1Ag%3F%C2%A01.%C2%9C%C3%B7%C3%8A%02%C3%80%C2%92W%C3%8C%C3%BA

然后……?(黑人问号脸),不得不说出题人是会玩的,差点以为搞了两次base64加密,原来是加密一次又解密,最后url转换一波。剩下的就跟上一题差不多了,生成key值的算法题目中已经给出,把给的enc转换回来, 逐个取值与key异或,将生成的ASCII值转换回来就完事了。

那么,走起来吧:

import urllib.parse
key = "HereIsFlagggg"
enc = "%C2%A6n%C2%87Y%1Ag%3F%C2%A01.%C2%9C%C3%B7%C3%8A%02%C3%80%C2%92W%C3%8C%C3%BA"
crypt =urllib.parse.unquote(enc)

s_box = list(range(256))
j = 0
for i in range(256):
    j = (j + s_box[i] + ord(key[i % len(key)])) % 256
    s_box[i], s_box[j] = s_box[j], s_box[i]
a = []

i = j = 0
for s in crypt:
    i = (i + 1) % 256
    j = (j + s_box[i]) % 256
    s_box[i], s_box[j] = s_box[j], s_box[i]
    t = (s_box[i] + s_box[j]) % 256
    k = s_box[t]
    
    a.append(chr(ord(s) ^ k))
flag = "".join(a)
print('flag=',flag)

最终flag get:

————20230818下午———— 

[SWPUCTF 2021 新生赛]re1

下载附件,是一个exe文件,先上die看下有没有壳:

【NSSCTF】刷题记录——[SWPUCTF 2021 新生赛]系列(REVERSE篇)_第1张图片

看出来是没壳的,而且是个64位文件,那么ida64来一下:

【NSSCTF】刷题记录——[SWPUCTF 2021 新生赛]系列(REVERSE篇)_第2张图片

按一下空格键,转换下显示模式,找到main函数后按F5转换成伪代码方便查看:

【NSSCTF】刷题记录——[SWPUCTF 2021 新生赛]系列(REVERSE篇)_第3张图片

 代码如下:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char Str2[1008]; // [rsp+20h] [rbp-60h] BYREF
  char Str1[1000]; // [rsp+410h] [rbp+390h] BYREF
  int i; // [rsp+7FCh] [rbp+77Ch]

  _main();
  strcpy(Str2, "{34sy_r3v3rs3}");
  printf("please put your flag:");
  scanf("%s", Str1);
  for ( i = 0; i <= 665; ++i )
  {
    if ( Str1[i] == 101 )
      Str1[i] = 51;
  }
  for ( i = 0; i <= 665; ++i )
  {
    if ( Str1[i] == 97 )
      Str1[i] = 52;
  }
  if ( strcmp(Str1, Str2) )
    printf("you are wrong,see again!");
  else
    printf("you are right!");
  system("pause");
  return 0;
}

这……有点太明显了啊,上面那个花括号里的……就是flag了,偷懒一把,手工把3换成e,4换成a,flag就出来了……

当然,按照正规程序,这样是不太行的,但我今天不想做了哈哈哈哈哈嗝……

————20230822———— 

[SWPUCTF 2021 新生赛]re2

下载附件,首先die

【NSSCTF】刷题记录——[SWPUCTF 2021 新生赛]系列(REVERSE篇)_第4张图片很好,无壳,64位,那么ida64走一波,找到main函数,伪代码看一眼,顺便注释一下:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char Str2[64]; // [rsp+20h] [rbp-90h] BYREF   #定义Str2字符串,长度64位
  char Str[68]; // [rsp+60h] [rbp-50h] BYREF    #定义Str字符串,长度68位
  int v7; // [rsp+A8h] [rbp-8h] #定义变量v7为整数类型
  int i; // [rsp+ACh] [rbp-4h]  #定义变量i为整数类型

  _main();
  strcpy(Str2, "ylqq]aycqyp{"); // 对Str2赋值
  printf(&Format);
  gets(Str); //要求输入Str
  v7 = strlen(Str); //令v7的值等于Str的长度值
  for ( i = 0; i < v7; ++i ) //令i为0,若i的值小于v7,则i+1
  {
    if ( (Str[i] <= 96 || Str[i] > 98) && (Str[i] <= 64 || Str[i] > 66) ) //若当前Str字符的ASCII值小于等于96或大于98的同时小于等于64或大于66
      Str[i] -= 2;  //则当前Str字符ASCII值-2
    else
      Str[i] += 24; //否则+24
  }

  if ( strcmp(Str, Str2) ) //比较Str与Str2字符串
    printf(&byte_404024);
  else
    printf(aBingo);
  system("pause");
  return 0;
}

看得出来,这里的Str经过for循环运算与Str2相等,则说明我们输入的就是flag了。本想用C语言写,然而……死去十几年的记忆终究是死去了,只好用python

flag=''
flag1=''
a=''
b=''
enco='ylqq]aycqyp{'
length=len(enco)
for i in range(length):
    if (ord(enco[i]) <= 94 or ord(enco[i]) > 96 ) and (ord(enco[i]) <= 64 or ord(enco[i]) > 66):
        a+=chr(ord(enco[i])+2)
       
    else:
        b+=chr(ord(enco[i])-24)
        
flag= "".join(a) 
flag1= "".join(b)
print(flag)
print(flag1)

 

运行结果是

提交flag、结果错误,啊这……看了一眼像是caesar,于是厚着脸皮手动改成NSSCTF{nss

_caesar}提交,成功……

P.S 严重吐槽CSDN的编辑器,太特么垃圾了

————20230824凌晨———— 

[SWPUCTF 2021 新生赛]fakerandom

题目源码如下:

import random
flag = 'xxxxxxxxxxxxxxxxxxxx'
random.seed(1)
l = []
for i in range(4):
    l.append(random.getrandbits(8))
result=[]
for i in range(len(l)):
    random.seed(l[i])
    for n in range(5):
        result.append(ord(flag[i*5+n])^random.getrandbits(8))
print(result)
# result = [201, 8, 198, 68, 131, 152, 186, 136, 13, 130, 190, 112, 251, 93, 212, 1, 31, 214, 116, 244]

这题目乍一看,不就是玩伪随机数嘛,一开始在分析的时候没有整明白random.seed()与random.getrandbits()函数的关系,以为直接从result中按顺序取值进行异或运算后解题

后面才发现random.seed()函数是用来改变随机数生成器的种子,没有参数时,每次生成的随机数是不一样的,而当seed()有参数时,每次生成的随机数是一样的。因此解题时同样需要通过random.seed()给定random.getrandbits()函数的种子

那么,本题源代码经注释如下:

import random
flag = 'xxxxxxxxxxxxxxxxxxxx' #定义flag字符串
random.seed(1) #设定以1为种子生成伪随机数,并将其作为getrandbits函数的种子
l = [] #定义空数组l
for i in range(4):
    l.append(random.getrandbits(8)) # 本for循环在0~255之间随机取4个值,并赋值给l数组
result=[] #定义空数组result
for i in range(len(l)): 
    random.seed(l[i])
    for n in range(5):
        result.append(ord(flag[i*5+n])^random.getrandbits(8)) #参照上一for循环,本for循环中,分别以l数组各值作为本for循环中的getrandbits函数的种子,并将flag各位(即x)的ASCII值与生成的随机数进行异或运算后赋值给result数组
print(result)
# result = [201, 8, 198, 68, 131, 152, 186, 136, 13, 130, 190, 112, 251, 93, 212, 1, 31, 214, 116, 244]

这样一看就明白多了,还是异或的老套路,只不过key由伪随机数构成,直接逆向就完事了

import random
flag = '' 
random.seed(1) 
l = [] 
result = [201, 8, 198, 68, 131, 152, 186, 136, 13, 130, 190, 112, 251, 93, 212, 1, 31, 214, 116, 244]
for i in range(4):
    l.append(random.getrandbits(8))

for i in range(len(l)): 
    random.seed(l[i])
    for n in range(5):
        flag+=chr(result[i*5+n]^random.getrandbits(8))
print(flag)

flag get

————20230825凌晨———— 

[SWPUCTF 2021 新生赛]非常简单的逻辑题

源码如下:

flag = 'xxxxxxxxxxxxxxxxxxxxx'
s = 'wesyvbniazxchjko1973652048@$+-&*<>'
result = ''
for i in range(len(flag)):
    s1 = ord(flag[i])//17
    s2 = ord(flag[i])%17
    result += s[(s1+i)%34]+s[-(s2+i+1)%34]
print(result)
# result = 'v0b9n1nkajz@j0c4jjo3oi1h1i937b395i5y5e0e$i'

注释一波:

flag = 'xxxxxxxxxxxxxxxxxxxxx'
s = 'wesyvbniazxchjko1973652048@$+-&*<>'
result = ''
for i in range(len(flag)):
    s1 = ord(flag[i])//17  #对x的ASCII值除以17后取整,定值为7
    s2 = ord(flag[i])%17   #对x的ASCII值除以17后取余数,定值为1
    print('ord(flag[i])=',ord(flag[i]),',i=',i,',s1=',s1,',s2=',s2)
    a=s1+i
    a1=a%34 # 取值范围为7~27
    b=s2+i+1
    b1=(-b)
    b2=b1%34 #负数取余,计算方式为-(b1%34),例i=0时,b=2,b1=-2,b2=-(2%34)=-(0余2),故b2=-2
    print('a=',a,',a1=',a1,',b=',b,',b1=',b1,',b2=',b2)
    c=s[a1]
    d=s[b1]
    print('c=',c,'d=',d)
    result += s[(s1+i)%34]+s[-(s2+i+1)%34] #令result值等于字符串s中第7~27位的值与第32~12位的值穿插叠加
    print(result)
    print('————————')
print(result)
# result = 'v0b9n1nkajz@j0c4jjo3oi1h1i937b395i5y5e0e$i'

然后愣是弄不懂要怎么解……先跳过

想了两个晚上也没想怎么把这题逆出来,看了其他师傅的也还是搞不明白,枯了……

只好换个思路,直接暴力破解……

flag=''
s = 'wesyvbniazxchjko1973652048@$+-&*<>'
result = 'v0b9n1nkajz@j0c4jjo3oi1h1i937b395i5y5e0e$i'
for i in range(len(result)//2):
    for j in range(0,255):
        s1=j//17
        s2=j%17
        tmp = s[(s1+i)%34]+s[-(s2+i+1)%34]
        if (tmp == result[i*2:i*2+2]):
            flag+=chr(j)
            break
print(flag)

flag get……

 有没有师傅行行好,教我一下怎么逆这个题啊,就是想不通T T

[SWPUCTF 2021 新生赛]fakebase

源码如下:

flag = 'xxxxxxxxxxxxxxxxxxx'

s_box = 'qwertyuiopasdfghjkzxcvb123456#$'
tmp = ''
for i in flag:
    tmp += str(bin(ord(i)))[2:].zfill(8)
b1 = int(tmp,2)
s = ''
while b1//31 != 0:
    s += s_box[b1%31]
    b1 = b1//31

print(s)

# s = u#k4ggia61egegzjuqz12jhfspfkay

好了不想做,先放着……

[SWPUCTF 2021 新生赛]easyapp

因为没有保存,所以这题的记录丢失……

过程就是先die一下看看有没有壳,发现是经过编译的,把扩展名改成zip

打开发现是个apk文件,用jdax破瓜后,在里面找到mainactivity和encoder

发现key是987654321,加密方式是异或

密文是一行unicode,转化后是一堆生僻字

解题代码如下:

result='棿棢棢棲棥棷棊棐棁棚棨棨棵棢棌'
key=987654321
flag=''
for i in result:
    a=ord(i)^key
    print(a)
    flag+= chr(a%128)
print(flag)

flag

[SWPUCTF 2021 新生赛]老鼠走迷宫

附件下载后又是没有扩展名,die后发现经过编译

【NSSCTF】刷题记录——[SWPUCTF 2021 新生赛]系列(REVERSE篇)_第5张图片

于是把扩展名改成.exe,然后根据大佬的思路python逆向的常见思路_wiiish的博客-CSDN博客,用pyinstxtractor破瓜,接着在爆出来的文件里,找到struct.py,用文件头16位覆盖5.py的文件头。

接着反编译。

本想用pycdc的,结果翻了一堆文章就是整不明白怎么用cmake搞定它,无奈之下用了uncompyle6。

反编译后的代码如下:

# uncompyle6 version 3.9.0
# Python bytecode version base 3.7.0 (3394)
# Decompiled from: Python 2.7.18 (v2.7.18:8d21aa21f2, Apr 20 2020, 13:25:05) [MSC v.1500 64 bit (AMD64)]
# Embedded file name: 5.py
# Compiled at: 1995-09-28 00:18:56
# Size of source mod 2**32: 272 bytes
import random, msvcrt
row, col = (12, 12)
i, j = (0, 0)
maze = [
 [
  1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  1, 1, 1, 1, 1, 1],
 [
  1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
  0, 0, 0, 1, 0, 1],
 [
  1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 
  1, 1, 0, 1, 0, 1],
 [
  1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 
  0, 0, 0, 1, 0, 1],
 [
  1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 
  0, 1, 1, 1, 0, 1],
 [
  1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 
  0, 1, 0, 0, 0, 1],
 [
  1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 
  1, 1, 1, 1, 0, 1],
 [
  1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 
  0, 0, 0, 1, 0, 1],
 [
  1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 
  1, 1, 0, 1, 0, 1],
 [
  1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 
  0, 1, 0, 0, 0, 1],
 [
  1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 
  0, 1, 1, 1, 0, 1],
 [
  1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 
  0, 1, 0, 0, 0, 1],
 [
  1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 
  0, 1, 0, 1, 1, 1],
 [
  1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 
  0, 1, 0, 1, 0, 1],
 [
  1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 
  0, 1, 0, 1, 0, 1],
 [
  1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 
  0, 1, 0, 1, 0, 1],
 [
  1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 
  1, 1, 0, 1, 0, 1],
 [
  1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 
  0, 1, 0, 0, 0, 1],
 [
  1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 
  0, 1, 1, 1, 0, 1],
 [
  1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 
  0, 0, 0, 1, 0, 1],
 [
  1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 
  1, 1, 0, 1, 0, 1],
 [
  1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 
  0, 1, 0, 1, 0, 1],
 [
  1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 
  0, 1, 0, 1, 0, 1],
 [
  1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 
  0, 1, 0, 0, 0, 1],
 [
  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
  1, 1, 1, 1, 0, 1]]
print('Mice walk in a maze: wasd to move,q to quit')
print("flag is the shortest path's md5,example:if the shortest path is wasdsdw,the flag is md5('wasdsdw')")
i, j = (0, 1)
n = 0
while 1:
    if i == row * 2:
        if j == col * 2 - 1:
            print('ohhhh!!!!you did it')
            break
        print('your position:({},{})'.format(i, j))
        inp = msvcrt.getch()
        n += 1
        ti, tj = i, j
        if b'a' == inp and i > 0:
            tj -= 1
        else:
            if b'w' == inp and j > 0:
                ti -= 1
            else:
                if b's' == inp and j < row * 2:
                    ti += 1
                else:
                    if b'd' == inp and i < col * 2:
                        tj += 1
                    else:
                        if b'q' == inp:
                            exit('bye!!')
                        else:
                            print('What???')
                            continue
        if maze[ti][tj] == 1:
            print(random.choice(['no wayy!!', "it's wall", 'nop']))
            continue
    elif maze[ti][tj] == 0:
        print(random.choice(['nice!!', 'yeah!!', 'Go on']))
        i, j = ti, tj

 把里面的maze单独拿出来

【NSSCTF】刷题记录——[SWPUCTF 2021 新生赛]系列(REVERSE篇)_第6张图片

 好吧……作为菜鸡,只好手动输入这个最短路径

path='sssssddssddssaaaassssddwwddddssssssaawwaassssddssaassddddwwddssddwwwwwwwwaawwddwwwwaaaawwddwwwwddssssddwwwwddddwwddddssaassaassddddssddssaassssssddsssssss'

 MD5加密即可得到flag

[SWPUCTF 2021 新生赛]PYRE(跪了)

die后发现又是个exe文件

【NSSCTF】刷题记录——[SWPUCTF 2021 新生赛]系列(REVERSE篇)_第7张图片

找到struct.py,用文件头16位覆盖code.py的文件头后用uncompyle6反编译,结果提示版本不符合……

好吧,只好用在线反编译工具,得到代码如下:

#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.9

import hashlib
import base64

def init(OOOOO00O0OO00OO00, OOO00O0000OOO0O00):
    OO00O000OOO0OOOOO = 0
    OOO00O0000OOO0O00 = hashlib.md5(OOO00O0000OOO0O00.encode()).hexdigest()
    OOO00OO0OOO00OOO0 = []
    for O0O00OO00OOO0O000 in range(256):
        OOOOO00O0OO00OO00.append(O0O00OO00OOO0O000)
        OOO00OO0OOO00OOO0.append(OOO00O0000OOO0O00[O0O00OO00OOO0O000 % len(OOO00O0000OOO0O00)])
    for O0O00OO00OOO0O000 in range(256):
        OO00O000OOO0OOOOO = (OO00O000OOO0OOOOO + OOOOO00O0OO00OO00[O0O00OO00OOO0O000] + ord(OOO00OO0OOO00OOO0[O0O00OO00OOO0O000])) % 256
        OOOOO00O0OO00OO00[O0O00OO00OOO0O000] = OOOOO00O0OO00OO00[OO00O000OOO0OOOOO]
        OOOOO00O0OO00OO00[OO00O000OOO0OOOOO] = OOOOO00O0OO00OO00[O0O00OO00OOO0O000]


def Encrypt(O0000O0OO00OO00O0, OO0OO00O00O0O00O0):
    OOOO0O00O00OOOOO0 = OO0O000O000O0O0O0 = 0
    O00O00OOOO00O0000 = ''
    for O0OO0O0O0OO0O0OOO in OO0OO00O00O0O00O0:
        OOOO0O00O00OOOOO0 = (OOOO0O00O00OOOOO0 + 1) % 256
        OO0O000O000O0O0O0 = (OO0O000O000O0O0O0 + O0000O0OO00OO00O0[OOOO0O00O00OOOOO0]) % 256
        O0000O0OO00OO00O0[OOOO0O00O00OOOOO0] = O0000O0OO00OO00O0[OO0O000O000O0O0O0]
        O0000O0OO00OO00O0[OO0O000O000O0O0O0] = O0000O0OO00OO00O0[OOOO0O00O00OOOOO0]
        O0OO0O0OOO00O0O00 = (O0000O0OO00OO00O0[OOOO0O00O00OOOOO0] + O0000O0OO00OO00O0[OO0O000O000O0O0O0]) % 256
        OOO000O0OOOOO00O0 = chr(ord(O0OO0O0O0OO0O0OOO) ^ O0000O0OO00OO00O0[(O0000O0OO00OO00O0[OOOO0O00O00OOOOO0] + O0000O0OO00OO00O0[OO0O000O000O0O0O0]) % 256])
        O00O00OOOO00O0000 += OOO000O0OOOOO00O0
    O00O00OOOO00O0000 = base64.b64encode(O00O00OOOO00O0000.encode())
    return O00O00OOOO00O0000

input_str = input('input flag pls:')
s = []
init(s, 'bJLVFYw3WI5ncGez')
if Encrypt(s, input_str).decode() == 'w4s1PUYsJ8OYwpRXVjvDkVPCgzIEJ27Dt2I=':
    print('good!')
    continue
print('nonono!')
continue

看不懂,放弃(摊手)

[SWPUCTF 2021 新生赛]简单的逻辑(跪了)

源码如下:

flag = 'xxxxxxxxxxxxxxxxxx'
flag = flag[::-1]
result = 0
for i in range(0,len(flag)-1):
    s1 = ord(flag[i])
    s2 = ord(flag[i+1])
    if i == 0:
        result = (s1<<8)^(s2<<4)^s2
    else:
        result = (result<<4)^((s1<<8)^(s2<<4)^s2)
print(result)
# result = 591620785604527668617886

注释一波:

flag = 'xxxxxxxxxxxxxxxxxx'
flag = flag[::-1]
print(flag)
result = 0
for i in range(0,len(flag)-1):
    print('i=',i)
    s1 = ord(flag[i])
    s2 = ord(flag[i+1])
    print('s1=',s1,',s2=',s2)
    if i == 0:
        result = (s1<<8)^(s2<<4)^s2  #给result赋初始值,初始值为120*256的值与120*16的值异或后,再与120异或,最终结果为32760
        print(s1<<8,s2<<4,result)
    else:
        result = (result<<4)^((s1<<8)^(s2<<4)^s2) #接着将初始result值重复进行上一步骤直至循环结束
        print(result)
        print('loop=',i)
print('————————————')
print(result)
# result = 591620785604527668617886

好了,不会(摊手)

[SWPUCTF 2021 新生赛]astJS(跪了)

附件一打开就知道是我不会的题(摊手)

————20230828凌晨————

你可能感兴趣的:(程序人生)