日常练习1
mango

2023/10/14

reverse_1

str1和str2要相等。str1是{hello_world},str2是‘0’

一开始还没注意到上面

1
Str[j] == 111

这个地方,鼠标右键可以转换为字符。

发现要把helloworld中的o都换成0

reverse_2

exeinfope查看后发现是elf文件,以为不可以在windows上分析,看了wp发现可以。

ida打开时选择所有文件

双击flag字符串:

跟上面那题一样要替换一些字母

内涵的软件

没啥意思,ida打开就看见flag了

比较坑的是BUU要都包上flag交。把DBAPP换成flag就好了

新年快乐

发现有壳

UPX -> Markus & Laszlo ver. [ 3.91 ]

尝试手工和自动脱壳

手工:

ctrl+f搜索popad

注意到这个jmp跳的比较不一样,F2设置断点,然后F9运行,F8,到入口了

然后使用x32dbg的插件Scylla脱壳,这里其实要修改IAT表,但我还不会

但可以拖到ida,发现程序正常了,找到flag

xor

打开后发现是个异或运算的

双击global,发现异或后的flag

此处可以改成数组方便复制,右键选array

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
m = ['f', 0xA, 'k', 0xC, 'w', '&', 'O', '.', '@', 0x11, 'x', 0xD, 'Z', ';', 'U', 0x11, 'p', 0x19,
'F', 0x1F, 'v', '"', 'M', '#', 'D', 0xE, 'g', 6, 'h', 0xF, 'G', '2', 'O']
flag = 'f'

for i in range(len(m) - 1):
if isinstance(m[i], str): # 若i是str
if isinstance(m[i + 1], str): # 若i和i+1都是str
s = ord(m[i]) ^ ord(m[i + 1])
else: # i是str,i+1不是
s = ord(m[i]) ^ m[i + 1]
else: # i不是str
if isinstance(m[i + 1], str): # 若i不是str,i+1是
s = m[i] ^ ord(m[i + 1])
else: # 都不是
s = m[i] ^ m[i + 1]
flag=flag+chr(s)
print(flag)

helloworld

拿到一个apk文件。搜了一下很多人用jadx或apkida做的,但是我还没下载。看到了用ida64也可以做,先试一下。

ida:

打开后直接搜索字符串flag √

jadx-gui:

全部勾选,然后加载更多,找

reverse_3

ctrl+alt+F 查看加密相关发现base64表

输入串为Str

v3是输入串的长度

Str经过base64加密后放到v4

v4放入Destination

循环对Destination中每个字符加上它的序号

最后成为Str2

所以只要把过程逆一下就好了

1
2
3
4
5
6
7
8
9
10
import base64

str2='e3nifIH9b_C@n@dH'
str1=''
for i in range(len(str2)):
str1=str1+chr(ord(str2[i])-i)
print(str1)

flag=base64.b64decode(str1)
print(flag)

最后的flag是{i_l0ve_you},有点子浪漫

不一样的flag

首先打开ida发现一串奇怪的字符*11110100001010000101111#

然后分析代码

漏截图exit(1)

把奇怪字符串放到v3

得到我们的输入v5

若v5=1,v3[25]–

若v5=2,v3[25]++

若v5=3,–v4

若v5=4,++v4

4*i 是因为int类型占有四个字节

这里判断v3[25]和v3[29]

在网上搜了发现这是迷宫问题。25和29是我的位置

49和35的ascii码正好对应1和#

那么就是要我移动到#位置

对  *11110100001010000101111#  进行拆解得到:

*1111

01000

01010

00010

1111#

flag{222441144222}

SimpleRev

_QWORD 64位整型

按 r 进行转化

数据存储是按照大端模式进行,但在读取时需要注意大小端序,下面是以char格式读取,故用时的小端序

src是char

*(_QWORD *)src = 0x534C43444ELL 小端序读取

src为NDCLS

key1=ADSFK

key3=kills

v9也要逆序

v9=hadow

text=key3++v9=killshadow

key1–>key

key=ADSFK

key=key+src=ADSFKNDCLS

key转小写

65–90 大写字母

97–122 小写字母

如果大写

如果小写

v1是flag

最后是爆破做的,因为%26逆不了

1
2
3
4
5
6
7
8
9
10
11
12
text = 'killshadow'
key = 'ADSFKNDCLS'
key2 = 'adsfkndcls'
v1 = ''

for i in range(len(text)):
for x in range(65, 123):
if text[i] == chr((x - 39 - ord(key2[i]) + 97) % 26 + 97):
v1 = v1 + chr(x)
break # 重要

print('flag{'+v1+'}')

Java逆向解密

用ja-gui打开

比较简单

1
2
3
4
5
6
7
key = [180, 136, 137, 147, 191, 137, 147, 191, 148, 136,
133, 191, 134, 140, 129, 135, 191, 65]
flag = ''
for i in range(len(key)):
s = chr(key[i] - 64 ^ 0x20)
flag=flag+s
print(flag)

al_easy_re

还没做出来,我服了。应该是花指令+反调试。花指令应该找的差不多了,反调试好像要在动态调试里做,我还不会…继续卡住。不过好的地方是更了解花指令了,以及ida的一些用法

412597

2023/10/15

luck_guy

简单的逆向

前面发现f1是GXY{do_not_

1
2
3
4
5
6
7
8
9
10
f2=[0x69,0x63,0x75,0x67,0x60,0x6f,0x66,0x7f]
f=''
for i in range(len(f2)):
if i%2==1:
f2[i]-=2
else:
f2[i]-=1
f=f+chr(f2[i])

print('GXY{do_not_'+f)

ACTFeasy_Re(未

查popad f9 f8 重载 dump

发现是一个简单的逆向

查string发现一个map

1
2
3
4
5
6
7
8
9
map='~}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)(\'&%$# !"'
v6=[65,67,84,70,123]
v4=[0x2a,0x46,0x27,0x22,0x4e,0x2c,0x22,0x28,0x49,0x3f,0x2b,0x40]

flag=''
for i in v4:
flag+=chr(map.find(chr(i))+1)

print(flag)

2023/10/22

JustRE

查壳,无

ida打开,看字符串,发现

双击进去,x看引用

填充两个占位符即可

hua(未

无壳,ida打开F5按不了,一片飘红

去花指令

这次遇到了call,jmp

还有莫名其妙的一些add esp, sub esp

要修改维持栈帧平衡

还遇到了leave,直接nop

1
2
3
leave   =
mov esp,esb
pop ebp

去完之后:

做不会了,什么玩意rc4,等wp

原来没有魔改。其实可以做的QAQ

刮开有奖

先看字符串,然后x

这里f5反汇编的伪代码里面有有a1+ 4 * i,a1+4 *result,这样的字符。但是在逆向的C语言代码中,要把它们的4去掉。因为int占4字节。如果是char的话就不用,因为char是1字节。

1
a[i]_address = base_address + i * data_type_size

这题的加密也有点难看懂,不过学到了可以不用看懂。。把它拖到dev跑就好了= =

但这里很奇怪啊,ida好像出错了,函数那里只传了v7,但是实际上是把下面的也传了

c语言跑出来3CEHJNSZagn

这里观察得到ak1w和V1Ax是string的两部分分别经过base64加密后得到的

解密:

ak1w=jMp

V1Ax=WP1

string[0]=v7[0]+34=’3’+34=’J’

string[1]=v[10]=’N’

string[2][3][4]=WP1

567=jMp

flag{UJWP1jMp}

简单注册机

apk文件,用jadx-gui打开

搜索flag无果,直接看MainActivity

发现相关代码

比较简单。这里一开始直接对字符串用下标报错了。学习了一下字符串转列表和列表转字符串

2023/10/23

FuelVM(未

wiki上的VM题目,前面的题目涉及到了不是很会,跟着教程学习一下。

如果很明确一个函数/变量的作用,可以按n给它重命名,方便后面分析

win32的一些api很有用。比如有输入框的时候,程序要获取用户的输入,那就要调用API,GetDlgItemTextA()

1
2
3
4
5
6
UINT GetDlgItemTextA(
HWND hDlg, //在哪个对话框查找目标控件
int nIDDlgItem,//目标控件的id
LPSTR lpString,
int cchMax//缓冲区长度
);

获取的输入字符串会保存在lpString里. 那么我们就可以打开 IDA 查找有交叉引用GetDlgItemTextA()的地方.

2023/10/25

pyre

kali里面使用pycdc反汇编

1
2
./pycdc xxx.pyc # 得到py代码
./pycdas xxx.pyc # 得到字节码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
code = ['\x1f', '\x12', '\x1d', '(', '0', '4', '\x01',
'\x06', '\x14', '4', ',', '\x1b', 'U', '?', 'o',
'6', '*', ':', '\x01', 'D', ';', '%', '\x13']
s=''
encode=[]
l=len(code)
print(l)
encode.append('\x13')
for i in range(l-1):
code[l-i-2]=chr(ord(code[l-i-2])^ord(code[l-i-1]))
print(code)
for i in range(l):
code[i]=(ord(code[i])-i)%128
for i in range(l):
s+=chr(code[i])
print(s)

这里发现(xxx+128)%128之后里面的+128消失了,是用来混淆的。

findit

打开是一个apk文件,使用jajx-gui打开,直接看MainActivity

发现只有下面那个循环和密文有关

然后本来想用java写的,但是发现忘干净了。还是py方便…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
b = ['p', 'v', 'k', 'q', '{', 'm', '1', '6', '4', '6', '7', '5', '2', '6', '2', '0', '3', '3', 'l', '4', 'm', '4', '9',
'l', 'n', 'p', '7', 'p', '9', 'm', 'n', 'k', '2', '8', 'k', '7', '5', '}']
y = []
for i in range(len(b)):
y.append('')
print(y)
for i in range(len(b)):
if (b[i] >= 'A' and b[i] <= 'Z') or (b[i] >= 'a' and b[i] <= 'z'):
y[i] = chr(ord(b[i]) + 16)
if (y[i] > 'Z' and y[i] < 'a') or y[i] >= 'z':
y[i] = chr(ord(y[i]) - 26)
else:
y[i] = b[i]
print(y)
print(''.join(y))
nt(''.join(y))

rome

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
v12 = 'Qsw3sj_lz4_Ujw@l'
# print(len(v12))
v12 = list(v12)
# print(v12)
flag = ''

for i in range(16):
for j in range(128): # ascii表上有127个字符,一个个试
x = j
if chr(x).isupper():
x = (x - 51) % 26 + 65
if chr(x).islower():
x = (x - 79) % 26 + 97
if chr(x)==v12[i]:
flag+=chr(j)

rsa

第一次拿到看起来不用ida的逆向

题目是rsa,里面flag是rsa加密后的flag

pub.key是公钥,拖到在线RSA公钥解析网站得到

不过到后面感觉题目有误

2023/10/26

login

简单的js审计,发现是rot13,用厨师打开

level1

简单的elf打开逆,给了output

主要是指针的位置不太一样要注意

1
2
3
4
5
6
7
8
9
10
output=[198,232,816,200,1536,300,6144,984,51200,570,92160,1200,565248,756,1474560,800,6291456,1782,65536000]
print(len(output))
flag=[]
for i in range(0,19):
if ((i+1)&1) !=0:
flag.append(chr(output[i]>>i+1))
else:
flag.append(chr(output[i]//(i+1))) # 整除,无小数

print(''.join(flag))

CrackRTF

无壳,直接ida然后F5

进入sub_40100A

发现了一个windows自带的加密库。第二个参数标识了使用何种加密算法。扔进gpt得知是sha1

然后脚本爆破:

1
2
3
4
5
6
7
8
9
10
import hashlib

flag = '@DBApp'
for i in range(100000,999999): # 构造字符串
s=str(i)+flag
x=hashlib.sha1(s.encode())
cnt=x.hexdigest()
if '6e32d0943418c2c' in cnt: # 检查cnt是否包含该哈希值
print(cnt)
print(str(i)+flag)

得到

1
2
6e32d0943418c2c33385bc35a1470250dd8923a9
123321@DBApp

123321即为第一次输入的六位密码

sub401019打开发现是md5,但是这次密码没有数值限制,很难爆破。然后看到下面的sub_40100F

FindResourceA是打开当前的.exe文件中资源文件的文件(可以把自己的资源文件加入.exe文件中)

然后看sub_401005

发现是把AAA取出来的值和第二次输入的密码异或

然后把这个值写入dbapp.rtf

先写入一个空白文件的肯定是文件头。

所以要得到第二次输入的密码就要把AAA取出的值和rtf的文件头异或。因为是六位密码,所以都取六位就好了。

关于AAA文件,可以使用Resource Hacker

1
2
3
4
5
6
7
8
s='{\\rtf1'
a=[0x05,0x7d,0x41,0x15,0x26,0x01]

flag=''
for i in range(0,len(s)):
x=ord(s[i])^a[i]
flag+=chr(x)
print(flag)

得到第二次输入的~!3a@0

然后输入到程序就生成了.rtf文件,打开后就得到flag啦。

这个题不看wp做不出来一点,首先是没遇到过windows自带的加密函数,对windows编程的了解还是太少了。意识到看官方文档和看课本的重要性。做题的时候有时会懒得细抠每一个函数,就会漏掉很多信息!要注意!一些不太明白的函数可以丢到gpt里先看看。

2023/10/27

maze

感觉找错迷宫了

re

脱壳

然后是除法逆向。除一下就得到flag了,但是出题人给少了一位,然后就要爆破一位。

2023/10/29

昨天在看hackgame,逆向的题都好难QAQ只会签到

还是看看newstar吧

segment

ida打开段界面,我的shift+f7会触发电脑功能,然后要在view里面找。

ELF

一段加密一段base64

这里要注意的是要转列表

Endian

题目是大端小端的意思

1
2
3
4
5
6
7
8
9
10
11
12
from Crypto.Util.number import long_to_bytes

v5 = [0x75553A1E, 0x7B583A03, 0x4D58220C, 0x7B50383D, 0x736B3819]
for i in range(len(v5)):
v5[i] = v5[i] ^ 0x12345678
v5[i] = long_to_bytes(v5[i])
v5[i] = str(v5[i], 'utf-8')
v5[i] = v5[i][::-1]
print(v5[i])

flag = ''.join(v5)
print(flag)

加密就是个异或,因为v5是用char存的,所以是小端序

2023/10/30

Androxor

简单的apk,异或

这里可以点左下角的smail

EzPE

打不开exe,用010打开后发现Dos头有误。修改Dos头为5A4De_Ifanew 修改为PE偏移0x80

然后文件修复成功

简单的异或

1
2
3
4
5
6
7
8
9
10
11
12
13
data = [0xA, 0xC, 0x4, 0x1F, 0x26, 0x6C, 0x43, 0x2D, 0x3C,
0xC, 0x54, 0x4C, 0x24, 0x25, 0x11, 0x6, 0x5, 0x3A,
0x7C, 0x51, 0x38, 0x1A, 3, 0xD, 1, 0x36, 0x1F, 0x12,
0x26, 4, 0x68, 0x5D, 0x3F, 0x2D, 0x37, 0x2A, 0x7D]
flag=[]
l=len(data)
flag.append(chr(data[l-1]))
l=l-1
while(l>0):
data[l-1]=data[l-1]^(l-1)^data[l]
flag.append(chr(data[l-1]))
l-=1
print(''.join(flag[::-1]))

注意数据不要复制错误了

lazy_activity

查找editTextPersonName2

makeText:创建并返回一个Toast对象

1
public static Toast makeText(Context context, CharSequence text, int duration)

Context context上下文对象,toast显示的对象

CharSequence text要显示的消息

int duration消息显示时长

PZthon

解压后得到一个exe,用peif打开之后发现它可能不止存在一个文件。然后用010打开之后发现有很多个py存在之中,所以考虑到是把pyc打包成exe了。然后解包:

在得到的文件夹里找到pzthon的pyc文件,然后反编译。

genshin_impact

基本逻辑是输入用户名和密码,用用户名进行rc4加密生成一个base64码表,然后用这个码表对密码进行base64加密

这里给了用户名的明文,那么就可以把码表跑出来

genshin.py

跑出来之后到厨师解一个换表的base64就可以了

2023/10/31

SMC

在这两个地方打断点,然后在ida里面动态调试,跳过反调试。然后在smc解密后查看加密的函数逻辑

c p后:

1
2
3
4
5
6
enc = [124, 130, 117, 123, 111, 71, 97, 87, 83, 37, 71, 83, 37, 132, 106, 39, 104, 39, 103, 106, 125, 132, 123, 53, 53,
72, 37, 123, 126, 106, 51, 113]
for i in range(len(enc)):
enc[i]=enc[i]-5
enc[i]=chr(enc[i]^0x11)
print(''.join(enc))

petals

去花

这是官方题解的花,但是我感觉还有别的。。而且我解不出来加密函数,蜂蜡!

C?C++?

是C#反编译,使用dnSpy

找到main

直接逆。这个界面让我没有这是伪代码的感觉,看着很怪。然后C#一点都不了解,这里面有个溢出的问题要%256,不是很理解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
array = [68, 75, 66, 72, 99, 19, 19, 78, 83, 74, 91, 86, 35, 39, 77, 85, 44, 89, 47, 92, 49, 88, 48, 91, 88, 102, 105,
51, 76, 115, -124, 125, 79, 122, -103]
text2 = "NEWSTAR"
# array2=text
for j in range(7):
array[j + 28] -= (ord(text2[j]) // 5) + 10
array[j + 21] -= j ^ 2
array[j + 14] -= 2 * j
array[j + 7] -= ord(text2[j]) % 5
array[j] -= j ^ -(ord(text2[j]) % 4)
for i in range(35):
array[i] += ord(' ')
array[i] -= i
print(chr(array[i] % 256), end='')

有机会要把这些比较常见的语言都学一下

2023/11/1

R4ndom

直接F5可以发现有个随机函数

在main函数前面翻翻可以发现ptrace和设置randomseed

所以这里有反调试和伪随机数

ptrace是一个Linux中用于调试的系统调用

1
2
3
4
5
6
Name
ptrace - process trace
SYNOPSIS
#include <sys/ptrace.h>
long ptrace(enum __ptrace_request request, pid_t pid,
void *addr, void *data);

ptrace提供了一种方法让父进程可以观察和控制其他进程的执行,检查和改变其核心映像以及寄存器。可以实现断点调试和系统调用跟踪。

函数使用request参数来指定希望执行的行为

request:

  • PTRACE_TRACEME:本进程将被其父进程跟踪,此时pid、addr、data没有实际意义,可以全部为0

    只能用在被调试的进程中,是被调试的子进程唯一能用的request选项,其他只能被父进程调试器使用

  • PTRACE_ATTACH:attach到一个指定的进程,使其成为当前进程跟踪的子进程(当前进程喜当爹),被跟踪的子进程的行为就等同于它进行了一次PTRACE_TRACEME,相当于gdb中的attach

  • PTRACE_CONT:继续运行之前停止的子进程,也可以向子进程发送指定的信号,相当于gdb中的continue

本题使用的反调试方法相当于当自己的爹。因为ptrace有规定每个进程只能被PTRACE_TRACEME一次,所以在程序开头执行一次ptrace(PTRACE_TRACEME,0,0,0),当gdb想调试它的时候就会发现以及执行了一次,不能再执行了,从而返回-1

绕过方法:

  1. 打patch,把ptrace函数的部分nop掉

  2. hook技术,把ptrace函数替换成自定义的ptrace函数,从而可以指定任意的返回值

  3. 利用gdb的catch,catch syscall ptrace会在发送ptrace调用的时候停下,因此在第二次停住时set $rax=0,绕过进程中ptrace(PTRACE_TRACEME,0,0,0)==-1的判断

这里面的数据要倒序读出应该是小端序的问题

1
flag[i] = Table[(16 * ((unsigned __int8)(data + rand_num % 255) >> 4) + 15) & (unsigned __int8)(data + rand_num % 255)];

关于这句加密我理解的是,16*和右移4位抵消,x为byte类型,x+15&x等于保留x的后4位数字,同时前四位也不变。所以就是flag=Table[flag+rand%255]

2023/11/2

easy_enc

搜索字符串找主函数

然后发现了4个加密函数,还有密文

前三个加密函数都是普通的加减,可以容易地逆过来

第四个是*52

无符号的char类型0-255会溢出,所以最后用了爆破。因为都是字符,所以范围比较小

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
__uint8_t enc[30] = {0xE8, 0x80, 0x84, 0x8, 0x18, 0x3C, 0x78, 0x68, 0x0, 0x70, 0x7C, 0x94, 0xC8,
0xE0, 0x10, 0xEC, 0xB4, 0xAC, 0x68, 0xA8, 0xC, 0x1C, 0x90, 0xCC, 0x54, 0x3C, 0x14, 0xDC, 0x30
};
char key[15] = "NewStarCTF";
for (int i = 0; i < 29; ++i) {
for (__uint8_t j = 32; j <= 127; ++j) { //ascii范围
__uint8_t tmp = j;
if (j >= 65 && j <= 90) {
j = (j - 52) % 26 + 65;
} else if (j >= 48 && j <= 57) {
j = (j - 45) % 10 + 48;
} else if (j >= 97 && j <= 122) {
j = (j - 89) % 26 + 97;
}
j = key[i % strlen(key)] + j; //为什么是i
j = ~j;
j *= 52;
if (j == enc[i]) {
if((tmp >= 'A' && tmp <= 'Z') || (tmp >= 'a' && tmp <= 'z')){
printf("%c", tmp);
}
}
j = tmp;
}
}
return 0;
}

AndroDbgme(未

使用apktool反编译

1
apktool d xxx.apk

找到Manifest,添加

1
android:debuggable="true"

重打包

1
apktool b xxx(文件夹)

重打包后的新apk在dist文件夹里面,挪到外面

生成密钥库

1
keytool -genkey -alias abc.keystore -keyalg RSA -validity 20000 -keystore abc.keystore

签名

1
jarsigner -verbose -keystore abc.keystore -signedjar 1_1.apk 1.apk abc.keystore

但后面就不知道这么搞了。jeb下载的好像不对,先搁置一下

去花

然后rc4

可以这样提取数组数据,在Edit里

是一个没有改动的RC4

EzDLL

题目有一个exe和一个dll

打开exe后会发现有几个tlscallback的函数

tlscallback可以初始化线程的本地数据,清理线程本地数据,执行其他线程特定的初始化和清理操作

存在反调试:

初始化了一个key数组传给dll:

这里IsDebuggerPresent()不存在调试器时的值应该为0

key=[5,20,13,14]

打开dll很容易发现一个魔改了的rc4:

使用脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include<stdio.h>
void encrypt(unsigned int* v, unsigned int* key){
    unsigned int l = v[0], r = v[1], sum = 1, delta = 999999999;   
for (size_t i = 0; i < 33; i++) {       
l += (((r << 3) ^ (r >> 4)) + r) ^ (sum + key[sum & 3]);       
sum += delta;       
r += (((l << 3) ^ (l >> 4)) + l) ^ (sum + key[(sum >> 11) & 3]);   
}   
v[0] = l;   
v[1] = r;
}
void decrypt(unsigned int* v, unsigned int* key) {   
unsigned int l = v[0], r = v[1], sum = 0, delta = 999999999;   
sum = 1+delta * 33;    for (size_t i = 0; i < 33; i++) {       
r -= (((l << 3) ^ (l >> 4)) + l) ^ (sum + key[(sum >> 11) & 3]);       
sum -= delta;       
l -= (((r << 3) ^ (r >> 4)) + r) ^ (sum + key[sum & 3]);   
}   
v[0] = l;   
v[1] = r;
}
unsigned char a[41] ={  130,67,163,137,111,186,128,200,248,180,86,189,179,65,178,141,218,68,14,4,3,46,56,222,18,84,173,137,149,48,99,33,223,13,148,17,220,178,208,17};
unsigned int key[]={5,20,13,14};
signed main(){   
unsigned int *t=(unsigned int*)a;       
for(int i=0;i<9;i+=2){       
decrypt(t+i,key);    }        for (int i = 0; i < 10; i++)    {        printf("%c%c%c%c", *((char*)&t[i] + 0), *((char*)&t[i] + 1), *((char*)&t[i] + 2), *((char*)&t[i] + 3));    }}
由 Hexo 驱动 & 主题 Keep
访客数 访问量