当前位置: 首页 > news >正文

SHCTF-REVERSE

前言

之前写的,一直没发,留个记录吧,万一哪天记录掉了起码在csdn有个念想

1.ezapk

反编译

快速定位关键函数

package com.mycheck.ezjv;import adrt.ADRTLogCatReader;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import java.nio.charset.StandardCharsets;
import java.util.Base64;/* loaded from: classes.dex */
public class MainActivity extends Activity {byte[] key = {(byte) 12, (byte) 15, (byte) 25, (byte) 30, (byte) 36};@Override // android.app.Activityprotected void onCreate(Bundle bundle) {ADRTLogCatReader.onContext(this, "com.aide.ui.mgai");super.onCreate(bundle);setContentView(R.layout.activity_main);Check(this);}public static String Encode(String str, byte[] bArr) {StringBuilder sb = new StringBuilder();for (int i = 0; i < str.length(); i++) {sb.append((char) (((char) (((char) (str.charAt(i) ^ bArr[i % bArr.length])) + 6)) * 2));}return Base64.getEncoder().encodeToString(sb.toString().getBytes(StandardCharsets.UTF_8));}public void Check(Context context) {((Button) findViewById(R.id.Button1)).setOnClickListener(new View.OnClickListener(this, (EditText) findViewById(R.id.test1), context) { // from class: com.mycheck.ezjv.MainActivity.100000000private final MainActivity this$0;private final Context val$context;private final EditText val$myedit;{this.this$0 = this;this.val$myedit = r9;this.val$context = context;}@Override // android.view.View.OnClickListenerpublic void onClick(View view) {if (!MainActivity.Encode(this.val$myedit.getText().toString(), this.this$0.key).equals("woLDgMOgw7hEwoJQw7zDtsKow7TDpMOMZMOow75QxIbDnsKmw6Z4UMK0w7rCklDCrMKqwqbDtMOOw6DDsg==")) {Toast.makeText(this.val$context, "Wrong! Try again~", 1).show();} else {Toast.makeText(this.val$context, "You Win!!", 1).show();}}});}
}

解密逻辑

  1. 字符串中的每个字符与一个循环使用的字节数组进行异或(XOR)操作。
  2. 对得到的结果加6。
  3. 将结果乘以2。
  4. 最后使用Base64编码。

解密脚本

import base64# 加密时使用的密钥
key = [12, 15, 25, 30, 36]def decode(encoded_str, key):# Base64 解码decoded_bytes = base64.b64decode(encoded_str)decoded_str = decoded_bytes.decode('utf-8')# 解密过程result = []for i in range(len(decoded_str)):ch = ord(decoded_str[i])ch = chr((ch // 2) - 6)ch = chr(ord(ch) ^ key[i % len(key)])result.append(ch)return ''.join(result)if __name__ == "__main__":encoded_str = "woLDgMOgw7hEwoJQw7zDtsKow7TDpMOMZMOow75QxIbDnsKmw6Z4UMK0w7rCklDCrMKqwqbDtMOOw6DDsg=="print("Decoded string:", decode(encoded_str, key))

7Ush87-akjxcy2Ju-dwia9;JSO-IQixnsm

验证一下

SHCTF{7Ush87-akjxcy2Ju-dwia9;JSO-IQixnsm}

2.rc4

看看sub_1200,再看看sub_12e2函数

很明显这是一个RC4

加密这里又异或了个0x66,这是魔改的一部分

写出解密脚本

def swap_bytes(a, b):return b, adef sub_1200(key, sbox_size=256):"""Initialize the S-box using the key."""sbox = list(range(sbox_size))j = 0for i in range(sbox_size):j = (j + sbox[i] + key[i % len(key)]) % sbox_sizesbox[i], sbox[j] = swap_bytes(sbox[i], sbox[j])return sboxdef decrypt(encrypted_data, sbox):"""Decrypt the data using the initialized S-box."""i, j = 0, 0decrypted_data = bytearray(len(encrypted_data))for k in range(len(encrypted_data)):i = (i + 1) % 256j = (j + sbox[i]) % 256sbox[i], sbox[j] = swap_bytes(sbox[i], sbox[j])temp = sbox[(sbox[i] + sbox[j]) % 256]decrypted_data[k] = encrypted_data[k] ^ temp ^ 0x66return decrypted_datadef main():# 加密后的 flag 数据 (从 v4 数组中获取)encrypted_flag = [0x5B3C8F65423FAB21,0x691AE7846E05170C,0x111F7077C3]# 将加密后的 flag 转换为字节数组encrypted_data = bytearray()for value in encrypted_flag:encrypted_data.extend(value.to_bytes(8, byteorder='little'))# 密钥 (从 v5 数组中获取)key = [0x212179654B6E6546]# 将密钥转换为字节数组key_bytes = bytearray()for value in key:key_bytes.extend(value.to_bytes(8, byteorder='little'))# 初始化 S-boxsbox = sub_1200(key_bytes)# 解密 flagdecrypted_flag = decrypt(encrypted_data, sbox)# 打印解密后的 flagprint("Decrypted Flag: ", end="")for byte in decrypted_flag:if 32 <= byte <= 126:  # Printable charactersprint(chr(byte), end="")else:print(f"\\x{byte:02x}", end="")print()if __name__ == "__main__":main()

输出一下

SHCTF{rc4_nice_ez!!!}

3.ezxor

查壳,发现无壳

拖进ida64位中,快速定位主函数

data = [-61, 105, 114, -60, 103, 74, -24, 17, 67, -49, 111, 0, -13, 68, 110, -8, 89, 73, -24, 78, 94, -30, 83, 67, -79, 92]

图中的数据提取出来

图中的解密逻辑

根据这个写出解密脚本

def decrypt_data():# 初始数据数组,根据提供的数据填充data = [-61, 105, 114, -60, 103, 74, -24, 17, 67, -49, 111, 0, -13, 68, 110, -8, 89, 73, -24, 78, 94, -30, 83, 67, -79, 92]# 逆向执行异或操作for i in range(26):mod_val = i % 3if mod_val == 1:data[i] ^= 0x21elif mod_val == 2:data[i] ^= 0x31else:data[i] ^= 0x90# 将解密后的字节转换为可读字符串decrypted_str = ''.join([chr(b if b >= 0 else b + 256) for b in data])print("Decrypted string:", decrypted_str)if __name__ == "__main__":decrypt_data()

SHCTF{x0r_N1ce_hxxxoorrr!}

4.gamegame

查壳,发现无壳,丢进ida64中,且发现是数独

模拟写出数独脚本

def is_safe(grid, row, col, num):"""Check if it's safe to place the number in the given position."""# Check the rowfor x in range(9):if grid[row][x] == num:return False# Check the columnfor x in range(9):if grid[x][col] == num:return False# Check the 3x3 subgridstart_row = row - row % 3start_col = col - col % 3for i in range(3):for j in range(3):if grid[i + start_row][j + start_col] == num:return Falsereturn Truedef print_grid(grid):"""Print the Sudoku grid."""for row in grid:print(" ".join(str(num) if num != 0 else '.' for num in row))def is_valid_sudoku(grid):"""Check if the Sudoku grid is valid."""for i in range(9):row_set = set()col_set = set()box_set = set()for j in range(9):if grid[i][j] != 0:if grid[i][j] in row_set:return Falserow_set.add(grid[i][j])if grid[j][i] != 0:if grid[j][i] in col_set:return Falsecol_set.add(grid[j][i])box_row = 3 * (i // 3)box_col = 3 * (i % 3)num = grid[box_row + j // 3][box_col + j % 3]if num != 0:if num in box_set:return Falsebox_set.add(num)return Truedef main():# Initialize an empty 9x9 Sudoku gridgrid = [[0 for _ in range(9)] for _ in range(9)]# Simulate user input of 51 numbersinputs = [5, 3, 4, 6, 7, 8, 9, 1, 2, 6, 7, 2, 1, 9, 5, 3, 4, 8, 1, 9, 8, 3, 4, 2, 5, 6, 7,8, 5, 9, 7, 6, 1, 4, 2, 3, 4, 2, 6, 8, 5, 3, 7, 9, 1, 7, 1, 3, 9, 2, 4, 8, 5, 6,9, 6, 1, 5, 3, 7, 2, 8, 4, 2, 8, 7, 4, 1, 9, 6, 3, 5, 3, 4, 5, 2, 8, 6, 1, 7, 9]v8 = 0while v8 < len(inputs):num = inputs[v8]placed = Falsefor i in range(9):for j in range(9):if grid[i][j] == 0:if is_safe(grid, i, j, num):grid[i][j] = numplaced = Truebreakif placed:breakif not placed:print("no")breakv8 += 1print(f"Placed {num} at position {v8}")print_grid(grid)if is_valid_sudoku(grid):print("yes,\nflag is your input")else:print("no")if __name__ == "__main__":main()

另外一个脚本

import copynon_puzzle = [[5, 3, 0, 0, 7, 0, 0, 0, 0],[6, 0, 0, 1, 9, 5, 0, 0, 0],[0, 9, 8, 0, 0, 0, 0, 6, 0],[8, 0, 0, 0, 6, 0, 0, 0, 3],[4, 0, 0, 8, 0, 3, 0, 0, 1],[7, 0, 0, 0, 2, 0, 0, 0, 6],[0, 6, 0, 0, 0, 0, 2, 8, 0],[0, 0, 0, 4, 1, 9, 0, 0, 5],[0, 0, 0, 0, 8, 0, 0, 7, 9]
]puzzle = copy.deepcopy(non_puzzle)def is_valid_move(puzzle, row, col, num):if num in puzzle[row]:return Falseif num in [puzzle[r][col] for r in range(9)]:return Falsestart_row, start_col = 3 * (row // 3), 3 * (col // 3)for i in range(3):for j in range(3):if puzzle[start_row + i][start_col + j] == num:return Falsereturn Truedef solve_sudoku(puzzle):for row in range(9):for col in range(9):if puzzle[row][col] == 0:for num in range(1, 10):if is_valid_move(puzzle, row, col, num):puzzle[row][col] = numif solve_sudoku(puzzle):return Truepuzzle[row][col] = 0return Falsereturn Truesolve_sudoku(puzzle)for i in range(len(non_puzzle)):for j in range(len(non_puzzle[i])):if non_puzzle[i][j] == 0:print(puzzle[i][j],end="")

然后我们输出我们刚刚打印的

468912723481342575971422657913948591537428763345261

468912723481342575971422657913948591537428763345261

shctf{468912723481342575971422657913948591537428763345261}

5.babytea

进入主函数

点进去函数

被魔改了一部分的XTEA算法

IDA字符串搜索找到主函数

密钥和密文都很明显。XTEA算法

下面对照给出解密脚本

#include <stdio.h>
#include <stdint.h>void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {unsigned int i;uint32_t v0=v[0], v1=v[1], delta=0x61C88747, sum=delta*num_rounds+0x8DDE2E40;for (i=0; i < num_rounds; i++) {   v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]) ^ v1;sum -= delta;v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]) ^ v0;}v[0]=v0; v[1]=v1;
}
int main()
{uint32_t enflag[] = {0x18C2E339, 0xE9550982, 0x108A30F7, 0x018430DD, 0xD5DE57B0, 0xD43E0740, 0xF42FDDE4, 0x968886E8,0xE5D77B79,0x685D758F};uint32_t key[4] = {1,1,2,3};for(int i=0;i<10;i+=2){uint32_t temp[2];        temp[0] = enflag[i];temp[1] = enflag[i+1];decipher(64,temp,key);printf("%c%c%c%c%c%c%c%c",*((char*)&temp[0]+0),*((char*)&temp[0]+1),*((char*)&temp[0]+2),*((char*)&temp[0]+3),*((char*)&temp[1]+0),*((char*)&temp[1]+1),*((char*)&temp[1]+2),*((char*)&temp[1]+3));}return 0;
}

delta=0x61C88747, sum=delta*num_rounds+0x8DDE2E40;

这是魔改的

shctf{962fd-464d-8f4f-f1fd-a6a0c987c569}

相关文章:

  • 【极致版】华为云Astro轻应用抽取IoTDA影子设备参数生成表格页面全流程
  • 如何在 iPhone 上恢复已删除的联系人:简短指南
  • OkHttp源码梳理
  • 2025 FIC wp
  • 【C语言】fprintf与perror对比,两种报错提示的方法
  • 【Webpack \ Vite】多环境配置
  • Redis一些小记录
  • lstm用电量预测+网页可视化大屏
  • 矩阵系统源码搭建热门音乐功能板块开发,支持OEM
  • 【音视频】音频编码实战
  • 用 Nodemon 解决 npm run serve 频繁重启服务
  • 华为仓颉编程语言的实际用法与使用领域详解
  • 【Arxiv 2025】Single Image Iterative Subject-driven Generation and Editing
  • jss html5-node.nodeType 属性用于表示节点的类型
  • PySpark中DataFrame应用升阶及UDF使用
  • 手写SpringMVC(基本框架)
  • 集成方案 | Docusign + 甄零科技,赋能企业海外业务高效增长!
  • OpenCV实验室工具的使用
  • 高能效计算:破解算力增长与能源约束的科技密码
  • 基于 Amazon RDS 数据库之间复制数据并屏蔽个人身份信息
  • 酒店保洁员调包住客港币,海南官方通报:成立调查组赴属地调查
  • 何立峰出席跨境贸易便利化专项行动部署会并讲话
  • 民政部党组成员、中国老龄协会会长刘振国任民政部副部长
  • 低轨卫星“千帆星座”已完成五批次组网卫星发射,未来还有这些计划
  • 今年一季度上海离境退税商品销售额7.6亿元,同比增85%
  • 体坛联播|AC米兰挺进意大利杯决赛,弗雷戴特宣布退役