REVERSE-PRACTICE-BUUCTF-32

[第四章 CTF之APK章]数字壳的传说

查壳,360加固
apk-shell
用frida脚本脱壳后,jadx-gui分析得到的dex文件
输入作为明文,输入的前6个字符作为密钥,字符串"123456"作为iv
对输入进行AES.CBC加密,得到的密文经base64编码后与已知的base64字符串比较
apk-main
分析AESUtils这个类
第19行把密钥扩展成长度为32的字符串,不足的补空格" "
第37行把iv扩展成长度为16的字符串,不足的补空格" "
apk-aes
密钥为输入的前6个字符,猜测是"N1BOOK"或者"n1book"
python解AES.CBC,当密钥为"n1book"时,解出flag

from Crypto.Cipher import AES
import base64
cipher="u0uYYmh4yRpPIT/zSP7EL/MOCliVoVLt3gHcrXDymLc="
cipher_str=base64.b64decode(cipher)
key_str="n1book"
key_str=key_str.ljust(32," ")
iv_str="123456"
iv_str=iv_str.ljust(16," ")
aes=AES.new(key_str,AES.MODE_CBC,iv_str)
print(aes.decrypt(cipher_str))
#n1book{h3ckF0rfun}

[第五章 CTF之RE章]Hello, RE

exe程序,ida打开后,在main函数中找到flag
re-flag

[第五章 CTF之RE章]BabyAlgorithm

elf文件,ida打开
main函数中,读取输入,验证输入长度是否为45,然后设置密钥,对输入进行RC4加密,得到的密文与已知的v8比较
re-main
已知密钥为"Nu1Lctf233",密文为v8,解RC4即可得到flag

#include<stdio.h>
void rc4_init(unsigned char* s, unsigned char* key, unsigned long Len_k)
{
	int i = 0, j = 0;
	char k[256] = { 0 };
	unsigned char tmp = 0;
	for (i = 0; i < 256; i++) {
		s[i] = i;
		k[i] = key[i % Len_k];
	}
	for (i = 0; i < 256; i++) {
		j = (j + s[i] + k[i]) % 256;
		tmp = s[i];
		s[i] = s[j];
		s[j] = tmp;
	}
}

/*
RC4加解密函数
unsigned char* Data     加解密的数据
unsigned long Len_D     加解密数据的长度
unsigned char* key      密钥
unsigned long Len_k     密钥长度
*/
void rc4_crypt(unsigned char* Data, unsigned long Len_D, unsigned char* key, unsigned long Len_k) //加解密
{
	unsigned char s[256];
	rc4_init(s, key, Len_k);
	int i = 0, j = 0, t = 0;
	unsigned long k = 0;
	unsigned char tmp;
	for (k = 0; k < Len_D; k++) {
		i = (i + 1) % 256;
		j = (j + s[i]) % 256;
		tmp = s[i];
		s[i] = s[j];
		s[j] = tmp;
		t = (s[i] + s[j]) % 256;
		Data[k] = Data[k] ^ s[t];
	}
}
void main()
{
	//密钥
	unsigned char key[] = "Nu1Lctf233";
	unsigned long key_len = sizeof(key) - 1;
	//密钥
	//unsigned char key[] = {};
	//unsigned long key_len = sizeof(key);

	//密文
	unsigned char data[] = { 0xC6, 0x21, 0xCA, 0xBF, 0x51, 0x43, 0x37, 0x31, 0x75, 0xE4,
		0x8E, 0xC0, 0x54, 0x6F, 0x8F, 0xEE, 0xF8, 0x5A, 0xA2, 0xC1,
		0xEB, 0xA5, 0x34, 0x6D, 0x71, 0x55, 0x08, 0x07, 0xB2, 0xA8,
		0x2F, 0xF4, 0x51, 0x8E, 0x0C, 0xCC, 0x33, 0x53, 0x31, 0x00,
		0x40, 0xD6, 0xCA, 0xEC, 0xD4 };
	//解密
	rc4_crypt(data, sizeof(data), key, key_len);
	for (int i = 0; i < sizeof(data); i++)
	{
		printf("%c", data[i]);
	}
	printf("\n");
	return;
}
//n1book{us1nG_f3atur3s_7o_de7erm1n3_4lg0ri7hm}

[第五章 CTF之RE章]BabyConst

elf文件,ida打开
main函数中,输入的长度为48,每四个一组,共12组,经过变换后与已知比较
可以看到每组的四个字符经变换后变成了一组包含16字节的数据,即16*8==128bit的数据
re-main
往下看sub_40085B函数,a1[2]~a1[5]分别设置成0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476
于是可以猜到是md5算法,这四个值是标准的幻数
参考:MD5算法原理及其实现
re-sub40085b
最后在md5这个网站解md5,每组解完拼接起来就是flag

arr=[0x39, 0x6D, 0xF0, 0xD2, 0x42, 0x41, 0xF8, 0x02, 0x16, 0x7A,
  0xDC, 0xC0, 0xD6, 0x10, 0x6E, 0xD3, 0xFE, 0x68, 0x6F, 0x27,
  0xE9, 0x00, 0x81, 0x6B, 0xB2, 0xB8, 0xBC, 0x63, 0xD7, 0x0D,
  0x40, 0x08, 0xD2, 0xCD, 0xB7, 0x10, 0x60, 0x4D, 0x69, 0x64,
  0xA8, 0x36, 0x25, 0x54, 0xF7, 0xDE, 0xF0, 0x96, 0xDF, 0xC4,
  0xF8, 0x47, 0xAC, 0xDE, 0x92, 0xAC, 0x23, 0xC4, 0x69, 0x4B,
  0xEF, 0x32, 0x50, 0x28, 0x46, 0x82, 0xA2, 0x4D, 0x59, 0xA9,
  0x8E, 0x7A, 0x66, 0xD8, 0xE0, 0xD3, 0x1F, 0xD9, 0xBD, 0x68,
  0x46, 0x04, 0xF6, 0x12, 0xD8, 0xA7, 0x1D, 0xEB, 0x0D, 0xFA,
  0x03, 0x5E, 0x3F, 0x06, 0xA5, 0x9B, 0x99, 0xAA, 0x58, 0x66,
  0x28, 0xD9, 0x70, 0x72, 0x73, 0x28, 0x6B, 0x4C, 0x87, 0x32,
  0xDC, 0xFF, 0xA6, 0xC9, 0xFE, 0x07, 0x74, 0x20, 0xE1, 0xDE,
  0xFD, 0xD7, 0xC8, 0x7B, 0x59, 0xCD, 0x1D, 0x73, 0xCB, 0x7F,
  0x25, 0x22, 0xCC, 0x3D, 0xF2, 0x0F, 0xF2, 0x98, 0x7E, 0x98,
  0x42, 0x7F, 0x05, 0xD2, 0xBE, 0x57, 0x03, 0xDD, 0x22, 0xDD,
  0xC3, 0x18, 0xEA, 0x07, 0x24, 0x80, 0x44, 0xD7, 0xEC, 0xCC,
  0xFF, 0xF5, 0x6B, 0xC4, 0x60, 0x70, 0xDA, 0xE9, 0xF9, 0x46,
  0x6C, 0x11, 0x76, 0x5D, 0x0C, 0x21, 0x0E, 0x49, 0x91, 0xA0,
  0x2A, 0x04, 0xE4, 0x21, 0x84, 0x9F, 0x2A, 0xB8, 0x9B, 0x7D,
  0x9E, 0xEA]
for i in range(0,len(arr),16):
    s=""
    for j in range(16):
        s+=hex(arr[i+j]).zfill(4).replace("0x","")
    print(s)
# 396df0d24241f802167adcc0d6106ed3 -->n1bo
# fe686f27e900816bb2b8bc63d70d4008 -->ok{U
# d2cdb710604d6964a8362554f7def096 -->5in9
# dfc4f847acde92ac23c4694bef325028 -->__c0
# 4682a24d59a98e7a66d8e0d31fd9bd68 -->n5ts
# 4604f612d8a71deb0dfa035e3f06a59b -->_7o_
# 99aa586628d9707273286b4c8732dcff -->1d3n
# a6c9fe077420e1defdd7c87b59cd1d73 -->t1fy
# cb7f2522cc3df20ff2987e98427f05d2 -->_mD5
# be5703dd22ddc318ea07248044d7eccc -->__41
# fff56bc46070dae9f9466c11765d0c21 -->gor1
# 0e4991a02a04e421849f2ab89b7d9eea -->thm}

#n1book{U5in9__c0n5ts_7o_1d3nt1fy_mD5__41gor1thm}

[第五章 CTF之RE章]BabyLib

elf文件,ida打开
交叉引用字符串"Input flag:"来到主逻辑函数
可以看到存在非常大的整数,而且65537很令人在意
RSA的题目做多了就会有感觉,65537通常是作为逆向题目中RSA的指数e,其他的大整数就分别是p,q和c
re-main
解RSA即可得到flag

import gmpy2
from Crypto.Util.number import long_to_bytes
p=9842210544704105105386460208892325341518023212707647450607909247791133264519200579173177912467785842558060968492186761162106356089009194470097546296829163
q=12972360952153818155692381381571252126631475184728971905301445264084096070607651598626783223094292740492828654265391639843199875189333033337169565006624907
n=p*q
e=65537
c=110694010334901653238216140152683772418101197298114114481381418739511015861349388028360214495059500357527716613334520805339266807313669925649167175211788624655809951516502907329949137499677877779584898365309802983718066683849944838484002656376845311375573423677826690834875095904482448693671735053088583663382
phin=(p-1)*(q-1)
d=gmpy2.invert(e,phin)
m=gmpy2.powmod(c,d,n)
print(long_to_bytes(m))
# n1book{1d3nt1fy_GMp_l1br4ry}

[第五章 CTF之RE章]easy_rust

rust语言,调试
变表base64,在这个地方找到变表
re-table
然后main函数中的第46行的cmp的第二个参数指向的是密文字符串
re-main
密文字符串,实际上在上面找到变表的那个位置,在"Input your flag:\n"与"Failed to read lineTrue!\nFalse!\n"之间就是密文字符串
re-cipher
解变表base64,第一个等号"=“隔断了flag的两个部分,最后的”=MlW"没有用
re-flag
拼接起来,中间加个"_",最后加上"}",于是flag为n1book{9o0d_j0b}
re-success

[第五章 CTF之RE章]easy_go

go语言,调试
输入的包络为"n1book{}",输入的总长度为21
比较验证在第79行的if语句
逻辑为:byte_561538[i] + byte_561518[i] * input[i] == byte_561528[i]
re-main
每个参与运算的整型都是8bit,写脚本时要注意截断

arr_18=[0xD3, 0x75, 0x9B, 0xF9, 0xA3, 0x87, 0xED, 0x93, 0x8D, 0xDD,
  0x77, 0xED, 0x67, 0x00, 0x00, 0x00]
arr_28=[0xB7, 0x9C, 0x79, 0x43, 0x9B, 0xAF, 0x94, 0xE4, 0x94, 0x71,
  0xEC, 0xEA, 0x8E, 0x00, 0x00, 0x00]
arr_38=[0xDB, 0x9E, 0xB7, 0x9A, 0x91, 0xCA, 0xA1, 0x6B, 0x97, 0xC1,
  0x74, 0xB3, 0x90, 0x00, 0x00, 0x00]
flag=""
for i in range(13):
    for j in range(32,128):
        if arr_28[i]==(arr_38[i]+(arr_18[i]*j)&0xff)&0xff:
            flag+=chr(j)
print("n1book{"+flag+"}")
#n1book{4Ff1n3_C1pH3R}

[第五章 CTF之RE章]easy_mfc

mfc的exe,用xspy找到一个函数
“OnCommand: notifycode=0000 id=0001,func= 0x00C61880(easy_mfc.exe+ 0x001880 )”
re-mfc
ida打开,去找偏移为"0x1880"的函数,读取输入,然后验证
re-func
进入sub_401910函数,可以看到,输入与v7循环异或,结果与v5比较
re-main
写逆异或脚本即可得到flag

v7=[0xBC, 0x9D, 0x8C, 0x92,0x40, 0x47, 0x86, 0x21,0xF5, 0xAC, 0x8F, 0xFD,
    0x68, 0xE4, 0xE9, 0x3A, 0xC0, 0x66, 0xB3, 0x64,0x7E, 0x79, 0xD3, 0x22,0x31, 0xF8]
v5=[0xD2, 0xAC, 0xEE, 0xFD,0x2F, 0x2C, 0xFD, 0x79,0xC5, 0xDE, 0xD0, 0x85,
    0x58, 0xB6, 0xB6, 0x0B,0xF5, 0x39, 0xC0, 0x54,0x21, 0x1F, 0xE2, 0x54,0x02, 0x85]
flag=""
for i in range(len(v7)):
    flag+=chr(v7[i]^v5[i])
print(flag)
#n1book{X0r_x0R_15_s0_f1v3}
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

P1umH0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值