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

——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看下有没有壳:

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

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

代码如下:

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

很好,无壳,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后发现经过编译

于是把扩展名改成.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],
 [
#### 总结

=============================================================

从转行到现在,差不多两年的时间,虽不能和大佬相比,但也是学了很多东西。我个人在学习的过程中,习惯简单做做笔记,方便自己复习的时候能够快速理解,现在将自己的笔记分享出来,和大家共同学习。



个人将这段时间所学的知识,分为三个阶段:

第一阶段:HTML&CSS&JavaScript基础



![](https://img-blog.csdnimg.cn/img_convert/3e0d5b0f6a97b823cc1ef22ff1a18191.png)

第二阶段:移动端开发技术



![](https://img-blog.csdnimg.cn/img_convert/fc21db0a800494796dc6408ce1486031.png)



第三阶段:前端常用框架



![](https://img-blog.csdnimg.cn/img_convert/644efd4ddd0f8d43535f1982ec0da6e4.png)



*   推荐学习方式:针对某个知识点,可以先简单过一下我的笔记,如果理解,那是最好,可以帮助快速解决问题;如果因为我的笔记太过简陋不理解,可以关注我以后我还会继续分享。



*   大厂的面试难在,针对一个基础知识点,比如JS的事件循环机制,不会上来就问概念,而是换个角度,从题目入手,看你是否真正掌握。所以对于概念的理解真的很重要。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值