当前位置:网站首页 > 编程语言 > 正文

破解16进制(破解16进制密码)



该题为正常ctf题与恶意脚本相结合的题目,cha为常规的re题目,clickme为恶意样本,在cha中拿到信息,然后根据clickme的逻辑解密。

cha的核心为比较经过换表base64然后与自己xor之后与内存中的32字节相比较

求解思路:

1.DFS爆破,因为前面的字节会影响后面的状态

2.利用前面的数据求和信息,筛选唯一解

爆破脚本:

convert_table = b'APet8BQfu9CRgv+DShw/ETixFUjyGVkzHWl0IXm1JYn2KZo3Lap4Mbq5Ncr6Ods7'
encrypted_flag = [0xD9, 0x40, 0x6F, 0xCA, 0x3D, 0x8F, 0x53, 0xB1, 0x8B, 0x34,
0x92, 0x8E, 0xF7, 0x19, 0x94, 0x61, 0x68, 0x71, 0x55, 0xB6,
0xCE, 0x5B, 0x71, 0x1A, 0x79, 0x42, 0x9D, 0x02, 0x93, 0x38,
0xAD, 0x1F, 0xD3, 0x24, 0x48, 0xFF, 0x21, 0xA2, 0x24, 0xBE,
0x95, 0x3A, 0xC1, 0xD2]

def convert(flag,index):
group = (index // 4) * 3
if index % 4 == 0:
return convert_table[flag[group] >> 2]
if index % 4 == 1:
return convert_table[(flag[group] << 4 & 0x30) + (flag[group + 1] >> 4)]
if index % 4 == 2:
return convert_table[(flag[group + 1] << 2 & 0x3c) + (flag[group + 2] >> 6)]
if index % 4 == 3:
return convert_table[flag[group + 2] & 0x3f]

def brup(flag):
cur_len = len(flag)
if cur_len != 0:
res = flag[cur_len-1] ^ convert(flag,cur_len-1)
if res != encrypted_flag[cur_len-1]:
return
if cur_len == 32:
sum = 0
for i in range(len(flag)):
sum = 19*sum + flag[i]
sum = sum & 0xffffffff
if sum == 0xD033A96A:
for i in flag:
print(i,end=',')
return
for i in range(256):
flag.append(i)
brup(flag)
flag.pop()

flag = bytearray()
brup(flag)







































clickme为babyuk家族,主要加密逻辑也类似。

核心加密逻辑在main_encrypt_file中:

  1. 根据curve25519算法(随机私钥和对应的公钥,共享密钥) 产生key nonce
  2. 根据key,nonce 产生cipher(golang_org_x_crypto_chacha20_newUnauthenticatedCipher)
  3. xorKeyStream加密文件
    1. 每0xA00000加密0x
    2. 加密整个文件
    3. 如果文件大小 < 0x
    4. 如果文件大小 > 0x
    5. 最后写入32字节公钥和固定标识

解密脚本:

package main

import (
"crypto/sha256"
"os"

"golang.org/x/crypto/chacha20"
"golang.org/x/crypto/curve25519"
)

func main() {

file, err := os.OpenFile("flag.png.xiran",os.O_RDWR,0)
if err != nil {
panic(err)
}

fileinfo,err := file.Stat()
if err != nil {
panic(err)
}

filesize := fileinfo.Size()
var start int64 = 0
end := filesize

privateKeyBob := [32]byte{144,16,46,165,100,230,124,220,241,66,166,239,164,119,237,82,49,23,47,236,139,107,73,98,43,49,237,80,249,117,245,115}

publicKeyAlice := make([]byte,32,32)

offset,err := file.Seek(filesize-32-6,0)
if err != nil {
panic(err)
}

file.ReadAt(publicKeyAlice,offset)

var sharedKeyAlice [32]byte
curve25519.ScalarMult(&sharedKeyAlice, &privateKeyBob, (*[32]byte)(publicKeyAlice))

var key [32]byte= sha256.Sum256(sharedKeyAlice[:])
var res [32]byte = sha256.Sum256(key[:])
nonce := res[10:22]


cipher, err := chacha20.NewUnauthenticatedCipher(key[:],nonce)
if err != nil {
panic(err)
}



buffer := make([]byte, 0x,0x)

for start < end {
file.ReadAt(buffer,start)
cipher.XORKeyStream(buffer,buffer)
file.WriteAt(buffer,start)
start += 0xA00000
}

if err := file.Close(); err != nil {
panic(err)
}

}

































































cha中的私钥如果纯静态的分析 只有爆破才行 能不能在cha运行时把 私钥dump出来

在尝试的过程中发现cha中,在.init_array中存在一个特殊的初始化函数,在这个函数中做了两个(或者一个)反调试:

1.ptrace(PTRACE_TRACEME) == -1 退出

2.读取某个内存中的值若为0 则退出(前面有个call 清除这个内存处的值)

在bypass这两个点之后,进入main之后 发现私钥对应的内存实际为0,这也和在ida中找不到它的xref呼应,我觉得这里作者的意思就是故意让程序运行不到main,所以正确做法只能爆破,不然直接进内存dump太简单了。



看雪ID:SleepAlone

https://bbs.kanxue.com/user-home-950548.htm

*本文为看雪论坛优秀文章,由 SleepAlone 原创,转载请注明来自看雪社区





# 往期推荐

1、记录一次BlackObfuscator去混淆流程

2、libEnccryptor vm 还原的探索

3、PHP PWN 入门调试

4、记录一次App H5逆向

5、CAN协议分析

球分享

球点赞

球在看

点击阅读原文查看更多

到此这篇激活成功教程16进制(激活成功教程16进制密码)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • 在线查看域名ip(在线查看域名证书有效期)2026-03-04 10:00:10
  • 预训练权重不匹配怎么办(预训练权重文件是什么)2026-03-04 10:00:10
  • 拆包裹是什么意思(拆包裹是什么意思啊)2026-03-04 10:00:10
  • nat类型检测在线(nat类型 检测)2026-03-04 10:00:10
  • 程序员入门必备键盘(程序员入门必备键盘图片)2026-03-04 10:00:10
  • tpami官网(tpo官网)2026-03-04 10:00:10
  • 国内驾照换国际驾照需要什么(国内驾校换国际驾照)2026-03-04 10:00:10
  • win10启动盘u盘制作(制作windows10启动u盘)2026-03-04 10:00:10
  • 本机信息APP(本机信息怎么恢复到桌面)2026-03-04 10:00:10
  • 读取文件权限在哪里设置(读取文件权限在哪里设置手机)2026-03-04 10:00:10
  • 全屏图片