□ k1=F1('pediy')函数代码
大写字母ASCII范围41h~5Ah
小写字母ASCII范围61h~7Ah
CODE:0040137E mov esi, [esp+arg_0] ;[ESP+4],'pediy'
CODE:00401382 push esi
CODE:00401383 mov al, [esi] ;取一个字符
CODE:00401385 test al, al ;检查是否还有字符
CODE:00401387 jz short loc_40139C ;没有字符了,跳转
CODE:00401389 cmp al, 41h ;41h uppercase 'A'
CODE:0040138B jb short loc_4013AC ;非字母异常处理
CODE:0040138D cmp al, 5Ah ;5Ah uppercase 'Z'
CODE:0040138F jnb short loc_401394;非uppercase,则转换为大写(字母判断逻辑不完整)
CODE:00401391 inc esi
CODE:00401392 jmp short loc_401383
CODE:00401394 ; ---------------------------------------------------------------------------
CODE:00401394 call sub_4013D2 ;Lower2UpperCase
CODE:00401399 inc esi
CODE:0040139A jmp short loc_401383
CODE:0040139C ; ---------------------------------------------------------------------------
CODE:0040139C pop esi ;'PEDIY'
CODE:0040139D call sub_4013C2 ;对'PEDIY'变形处理
CODE:004013A2 xor edi, 5678h ;对得到的结果异或
CODE:004013A8 mov eax, edi ;结果放入eax,准备结束当前子程序
CODE:004013AA jmp short locret_4013C1
CODE:004013AC ; ---------------------------------------------------------------------------
CODE:004013AC pop esi ; 如果输入非字母,出错
CODE:004013AD push 30h ; uType,Style
CODE:004013AF push offset aError ; "Error! ",Title
CODE:004013B4 push offset aIncorrectTryAg ; "Incorrect!,Try Again",text
CODE:004013B9 push dword ptr [ebp+8] ; hWnd
CODE:004013BC call MessageBoxA
CODE:004013C1 retn
CODE:004013C2 ; =============== S U B R O U T I N E ===============
CODE:004013C2 xor edi, edi ; ”PEDIY“变形处理,当前指令EDI clear
CODE:004013C4 xor ebx, ebx
CODE:004013C6 mov bl, [esi] ;"PEDIY"中取一个字符
CODE:004013C8 test bl, bl
CODE:004013CA jz short locret_4013D1
CODE:004013CC add edi, ebx ;EDI=EDI+EBX
CODE:004013CE inc esi
CODE:004013CF jmp short loc_4013C6
CODE:004013D1 retn
CODE:004013D2 ; =============== S U B R O U T I N E
CODE:004013D2 sub al, 20h
CODE:004013D4 mov [esi], al
CODE:004013D6 retn
使用C语言描述上面的代码
int F1(char *name)
{
int i,k1=0;
char ch;
for(i=0;name[i]!=0;i++)
{
ch=name[i];
if (ch<'A') break;
k1+=(ch>'Z')?(ch-32):ch;
}
k1=k1^0x5678;
return k1;
}
□ k2=F2('1234')函数代码
CODE:004013D8 xor eax, eax
CODE:004013DA xor edi, edi
CODE:004013DC xor ebx, ebx
CODE:004013DE mov esi, [esp+arg_0] ;ESI指向输入的序列号code[i]
CODE:004013E2 mov al, 0Ah
CODE:004013E4 mov bl, [esi]
CODE:004013E6 test bl, bl ;检查code[i]中的是否还有数字
CODE:004013E8 jz short loc_4013F5
CODE:004013EA sub bl, 30h ;EBX=BL-30h=code[i]-30h
CODE:004013ED imul edi, eax ;EDI=EDI*10,10进制左移1位
CODE:004013F0 add edi, ebx ;EDI=EDI+EBX=EDI+(code[i]-30h)
CODE:004013F2 inc esi
CODE:004013F3 jmp short loc_4013E2
CODE:004013F5 ; ---------------------------------------------------------------------------
CODE:004013F5 xor edi, 1234h ;最后对EDI做异或运算
CODE:004013FB mov ebx, edi
CODE:004013FD retn
使用C语言描述上面的代码
int F2(char *code)
{
int i,k2=0;
for(i=0;code[i]!=0;i++)
{
k2=k2*10+code[i]-48;
//如果a的值为'0'到'9'这10个字符之一,则a-48相当于将字符转换为数值。
//若a='5',则a-48=5。其中48是'0'的ASCII码
}
k2=k2^0x1234;
return k2;
}
注册机算法分析
核心思路
® 只要满足k1=k2注册就成功;
® 写注册机就要对F1或F2做逆变换,F1('n')=F2('s')这样'n','s'间就可自由转换;
算法选择
® 那么由F2=>F1方便,还是反过来方便 ?
® 如果从用户名算出序列号,只要找到F2的逆函数F1(name)=k1=F_2^(−1) (serial)
® 由于F_2^(−1) 函数有多个解
注册机代码
//注意:name[i]的位数是10位,原因见其调用的GetDlgItemTexstA函数
int keygen(char *name)
{
int i, k1 = 0,k2=0;
char ch;
for (i = 0;name[i] != 0&&i<=9;i++)
{
ch = name[i];
if (ch<'A') break;
k1 += (ch>'Z') ? (ch - 32) : ch;
}
k2 = k1 ^ 0x5678^0x1234;
return k2;
}
def maze():
x=['2221','2223','2211','0100','1110','0333','1111','1211','0112','2332','3303','3222','3221','1100','1111','2233']
retn='0b'
#base4 conver to base2
for ele in x:
for atom in ele:
retn+=bin(int(atom))[2:].zfill(2)
retn=hex(int(retn,2))[2:].upper() #base2 to base16
print('maze')
for ele in range(int(len(retn)/4)):
print(retn[ele*4:ele*4+4],end=' ')
print()
print('*'*52)
return retn
def key(usr):
sumX=0
print('*'*52+'\n'+usr)
for char in usr:
sumX+=ord(char)
print(str(hex(ord(char))[2:]),end=' ')
print()
print('*'*52)
sumX='0x'+hex(sumX)[-2:] #取求和结果低位8字节
lost=maze() #hex value "A9AB..." #准备异或运算
retn=''
for pair in range(int(len(lost)/2)):
result='0x'+lost[pair*2:pair*2+2]
retn+=hex(int(result,16)^int(sumX,16))[2:].upper()
print('key')
for ele in range(int(len(retn)/4)):
print(retn[ele*4:ele*4+4],end=' ')
print()
print('*'*52)
return retn
def getasm(fromX,to,range1,range2): #注意,python中from是系统关键字,不能当成变量使用,所以使用fromX
fp=open(r'd:\code.txt','w')
fp.write('地址\t\t指令\t\t\t\t//偏移\t访问内存\n')
for ea in range(fromX,to+1):
cmd=GetMnem(ea) #获取ea地址处汇编助记符,IDAapi
if ( cmd[:3]=='mov' ) or ( cmd[:3]=='lea'):
opcode=Dword(NextNotTail(ea)-4) #获取mov cl,byte ptr ds:[41AEB0]指令中的0x0041AEB0
if opcode>0x80000000:
opcode=opcode^((2**32)-1)+1 #计算负数的补码
print('->%08x %08x' %(ea,opcode))
if opcode>=range1 and opcode<=range2:
delta=opcode-range1 #ebp - 256 -->256
eaX=("%08x" %ea).upper()+'\t'
opcode=("%08x" %opcode).upper()+'\t'
fp.write(eaX+GetDisasm(ea)+'\t'+opcode+'\n')
MakeComm(ea,("\t//ebp-0x%04x" %delta).upper()); #加注释到IDA中
fp.close()
print('finished!')
#define F,G,H,I basic MD5 functions
f = lambda x,y,z: (x&y) | ((x^(0xffffffff))&z)
g = lambda x,y,z: (x&z) | (y&(z^(0xffffffff)))
h = lambda x,y,z: x^y^z
i = lambda x,y,z: y^(x | (z^0xffffffff))
#ROTATE_LEFT rotates x left n bits
rotate_left = lambda x,n: eval('0b'+bin(x<<n)[2:].zfill(32)[-32:]) | (x>>(32-n))
'''
ff,gg,hh,ii transformations for rounds 1,2,3 and 4
a,b,c,d is MD5 initialization constants
eleM is 32bit of plaintext
sinN = hex(int(abs((2**32)*sin(i)))) ,i=1~64
rol -->rotate_left X bits
f = lambda x,y,z: (x&y) | ((x^(0xffffffff)+1)&z)
'''
def ff(a,b,c,d,eleM,rolX,sinN):
a+=f(b,c,d)+eleM+sinN
a=eval('0x'+hex(a)[2:].zfill(8)[-8:])
a=rotate_left(a,rolX)+b
a=eval('0x'+hex(a)[2:].zfill(8)[-8:])
return a
def gg(a,b,c,d,eleM,rolX,sinN):
a+=g(b,c,d)+eleM+sinN
a=eval('0x'+hex(a)[2:].zfill(8)[-8:])
a=rotate_left(a,rolX)+b
a=eval('0x'+hex(a)[2:].zfill(8)[-8:])
return a
def hh(a,b,c,d,eleM,rolX,sinN):
a+=h(b,c,d)+eleM+sinN
a=eval('0x'+hex(a)[2:].zfill(8)[-8:])
a=rotate_left(a,rolX)+b
a=eval('0x'+hex(a)[2:].zfill(8)[-8:])
return a
def ii(a,b,c,d,eleM,rolX,sinN):
a+=i(b,c,d)+eleM+sinN
a=eval('0x'+hex(a)[2:].zfill(8)[-8:])
a=rotate_left(a,rolX)+b
a=eval('0x'+hex(a)[2:].zfill(8)[-8:])
return a
def decode(self,byteLst512):
'''
decode 512bit chars to 512bit numbers , total 64 ascii chars,
every 4 chrs convert to 1 number
byteLst512=open(FN,'rb').read(64) -> byteLst=[64,254,0,...]
lst32=[ele32bitA,ele32bitB,...], len(lst32)=16
ele32 -->0x32303135 -->(LE) 0x35313032
'''
lst32=[]
for i in range(int(64/4)):
tmp=''
for bit in byteLst512[i*4:i*4+4]:
tmp+=hex(bit)[2:].zfill(2)
lst32.append(eval('0x'+tmp[6:8]+tmp[4:6]+tmp[2:4]+tmp[0:2]))
return lst32
def encode(self,lst32):
'''
lst32= [ele32bitA,ele32bitB,...], len(_out)=16 , type(ele32bitA)==int"
_out=[ele4bitA,ele4bitB,...] -->byteLst
Update( _out, Len ) -->
MD5Transform( state[4], _out)
'''
tmp=''
byteLst=[]
for ele in lst32:
tmp+=hex(ele)[2:].zfill(8)
for idx in range(int(len(tmp)/2)):
byteLst.append(eval('0x'+tmp[idx*2:idx*2+2]))
return byteLst
#Round 3
a = hh (a, b, c, d, x[ 5], S31, 0xfffa3942)
d = hh (d, a, b, c, x[ 8], S32, 0x8771f681)
c = hh (c, d, a, b, x[11], S33, 0x6d9d6122)
b = hh (b, c, d, a, x[14], S34, 0xfde5380c)
a = hh (a, b, c, d, x[ 1], S31, 0xa4beea44)
d = hh (d, a, b, c, x[ 4], S32, 0x4bdecfa9)
c = hh (c, d, a, b, x[ 7], S33, 0xf6bb4b60)
b = hh (b, c, d, a, x[10], S34, 0xbebfbc70)
a = hh (a, b, c, d, x[13], S31, 0x289b7ec6)
d = hh (d, a, b, c, x[ 0], S32, 0xeaa127fa)
c = hh (c, d, a, b, x[ 3], S33, 0xd4ef3085)
b = hh (b, c, d, a, x[ 6], S34, 0x4881d05)
a = hh (a, b, c, d, x[ 9], S31, 0xd9d4d039)
d = hh (d, a, b, c, x[12], S32, 0xe6db99e5)
c = hh (c, d, a, b, x[15], S33, 0x1fa27cf8)
b = hh (b, c, d, a, x[ 2], S34, 0xc4ac5665)
#Round 4
a = ii (a, b, c, d, x[ 0], S41, 0xf4292244)
d = ii (d, a, b, c, x[ 7], S42, 0x432aff97)
c = ii (c, d, a, b, x[14], S43, 0xab9423a7)
b = ii (b, c, d, a, x[ 5], S44, 0xfc93a039) #error
a = ii (a, b, c, d, x[12], S41, 0x655b59c3)
d = ii (d, a, b, c, x[ 3], S42, 0x8f0ccc92)
c = ii (c, d, a, b, x[10], S43, 0xffeff47d)
b = ii (b, c, d, a, x[ 1], S44, 0x85845dd1)
a = ii (a, b, c, d, x[ 8], S41, 0x6fa87e4f)
d = ii (d, a, b, c, x[15], S42, 0xfe2ce6e0)
c = ii (c, d, a, b, x[ 6], S43, 0xa3014314)
b = ii (b, c, d, a, x[13], S44, 0x4e0811a1)
a = ii (a, b, c, d, x[ 4], S41, 0xf7537e82)
d = ii (d, a, b, c, x[11], S42, 0xbd3af235)
c = ii (c, d, a, b, x[ 2], S43, 0x2ad7d2bb)
b = ii (b, c, d, a, x[ 9], S44, 0xeb86d391)
self.aa += a
self.aa=eval('0x'+hex(self.aa)[2:].zfill(8)[-8:])
self.bb += b
self.bb=eval('0x'+hex(self.bb)[2:].zfill(8)[-8:])
self.cc += c
self.cc=eval('0x'+hex(self.cc)[2:].zfill(8)[-8:])
self.dd += d
self.dd=eval('0x'+hex(self.dd)[2:].zfill(8)[-8:])
def update(self,ordchrLst):
'''
pad self.buffer64 --> md5Transform
update self.count bits(all process bits)
md5Transform 512bit blocks
remain ordchrLst store in self.buffer
'''
index=self.count%64
partLen=64-index
self.count+=len(ordchrLst)
#pading self.buffer64
if len(ordchrLst)>=partLen:
self.buffer64.extend([ordchrLst.pop() for i in range(64-len(self.buffer64))])
self.md5Transform(self.buffer64)
loopN=int(len(ordchrLst)/64)
for idx in range(loopN):
self.md5Transform(ordchrLst[idx*64:idx*64+64])
ordchrLst=ordchrLst[loopN*64:]
else:
self.buffer64.extend(ordchrLst)
def final(self):
'''
padding len=448(mod512)
append len(msg) -->64bits
md5Transform --> hash val
'''
if self.count > 2**64:
self.count=self.count & (2**64-1)
tmp=hex(self.count<<3)[2:].zfill(16)
bits=[]
for idx in range(int(len(tmp)/2)):
bits.append(eval('0x'+tmp[idx*2:idx*2+2]))
index=self.count % 64
padLen=0
if index < 56:
padLen=56 - index
else:
padLen=120 - index
self.update(PADDING64[:padLen])
self.update(bits)
lst=[]
tmp=[self.aa,self.bb,self.cc,self.dd] #LE
for ele in tmp:
ele=hex(ele)[2:].zfill(8)
ele=eval('0x'+ele[6:9]+ele[4:6]+ele[2:4]+ele[0:2])
lst.append(ele)
tmp=lst
self.digestRaw16=self.encode(tmp)
for ele in tmp:
self.digestChars+=hex(ele)[2:].zfill(2)
def digestFile(self,filename):
self.__init__()
try:
f=open(filename,'rb')
except Exception as e:
print(str(e))
sys.exit(1)
buf=list(f.read(1024))
while buf:
self.update(buf)
buf=list(f.read(1024))
self.final()
f.close()
return self.digestChars
self.bb=0x10325476
self.bb += b
self.bb=self.bb&0xffffffff
self.dd=c_uint(0x10325476)
self.dd.value += d
七. 移位处理BE LE的转换,提升处理效率
def decode(self,byteLst512):
'''
decode 512bit chars to 512bit numbers , total 64 ascii chars,
every 4 chrs convert to 1 number
byteLst512=open(FN,'rb').read(64) -> byteLst=[64,254,0,...]
lst32=[ele32bitA,ele32bitB,...], len(lst32)=16
ele32 -->0x32303135 -->(LE) 0x35313032
'''
lst32=[]
for i in range(int(64/4)):
tmp=''
for bit in byteLst512[i*4:i*4+4]:
tmp+=hex(bit)[2:].zfill(2)
lst32.append(eval('0x'+tmp[6:8]+tmp[4:6]+tmp[2:4]+tmp[0:2]))
return lst32
def decodeX(self,byteLst512):
lst32=[]
for idx in range(int(64/4)):
sublst=byteLst512[idx*4:idx*4+4]
lst32.append(sublst[0] | (sublst[1]<<8) | \
(sublst[2]<<16) | (sublst[3]<<24))
return lst32
使用上面的方面优化函数后,计算1.29MB的程序用时3.75秒
def encode(self,lst32):
'''
lst32= [ele32bitA,ele32bitB,...], len(_out)=16 , type(ele32bitA)==int"
_out=[ele4bitA,ele4bitB,...] -->byteLst
Update( _out, Len ) -->
MD5Transform( state[4], _out)
'''
tmp=''
byteLst=[]
for ele in lst32:
tmp+=hex(ele)[2:].zfill(8)
for idx in range(int(len(tmp)/2)):
byteLst.append(eval('0x'+tmp[idx*2:idx*2+2]))
return byteLst
def encode(self,lst32):
'''
lst32= [ele32bitA,ele32bitB,...], len(byteLst)=16 , type(ele32bitA)==int"
byteLst=[ele4bitA,ele4bitB,...] -->byteLst,type(ele4bitA)==int
'''
byteLst=[]
for ele in lst32:
byteLst.append(ele&0xff)
byteLst.append((ele>>8)&0xff)
byteLst.append((ele>>16)&0xff)
byteLst.append((ele>>24)&0xff)
return byteLst
def final(self):
'''
padding len=448(mod512)
append len(msg) -->64bits
md5Transform --> hash val
'''
if self.count > 2**64:
self.count=self.count & (2**64-1)
#encode self.count -->
tmp=hex(self.count<<3)[2:].zfill(16)
bits=[]
for idx in range(int(len(tmp)/8)):
bits.append(eval('0x'+tmp[idx*8+6:idx*8+8]))
bits.append(eval('0x'+tmp[idx*8+4:idx*8+6]))
bits.append(eval('0x'+tmp[idx*8+2:idx*8+4]))
bits.append(eval('0x'+tmp[idx*8:idx*8+2]))
bits=bits[4:8]+bits[0:4]
index=self.count % 64
padLen=0
if index < 56:
padLen=56 - index
else:
padLen=120 - index
self.update(PADDING64[:padLen])
self.update(bits)
lst=[]
tmp=[self.aa.value,self.bb.value,self.cc.value,self.dd.value] #LE
for ele in tmp:
ele=hex(ele)[2:].zfill(8)
ele=eval('0x'+ele[6:9]+ele[4:6]+ele[2:4]+ele[0:2])
lst.append(ele)
tmp=lst
self.digestRaw16=self.encode(tmp)
def final(self):
'''
padding len=448(mod512)
append len(msg) -->64bits
md5Transform --> hash val
'''
count = [self.count[0],self.count[1]]
bits=self.encode(count) #return byteLst,size=64bits
index=(self.count[0]>>3) &0x3f #self.count[0]_bytes mod 64
if index < 56:
padLen=56 - index
else:
padLen=120 - index
self.update(PADDING64[:padLen])
self.update(bits)
self.digestRaw16=('%#x %#x %#x %#x' \
%(self.aa.value,self.bb.value,self.cc.value,self.dd.value)).split()
tmp=self.encode([self.aa.value,self.bb.value,self.cc.value,self.dd.value])
self.digestChars=''.join([hex(i)[2:].zfill(2) for i in tmp])
八. 使用ctypes array来保持C代码与Py代码一致性
def update(self,ordchrLst):
'''
pad self.buffer64 --> md5Transform
update self.count bits(all process bits)
md5Transform 512bit blocks
remain ordchrLst store in self.buffer
'''
index=len(self.buffer64)%64
partLen=64-index
self.count+=len(ordchrLst)
#pading self.buffer64
if len(ordchrLst)>=partLen:
self.buffer64.extend([ordchrLst.pop(0) for i in range(64-len(self.buffer64))])
self.md5Transform(self.buffer64)
self.buffer64=[]
loopN=int(len(ordchrLst)/64)
for idx in range(loopN):
self.md5Transform(ordchrLst[:64])
ordchrLst=ordchrLst[64:]
self.buffer64.extend(ordchrLst)
else:
self.buffer64.extend(ordchrLst)
def update(self,ordchrLst):
'''
pad self.buffer64 for md5Transform()
update self.count bits(all process bits)
md5Transform 512bit blocks
remain ordchrLst store in self.buffer64
self.count=c_uint*2
'''
index=len(self.buffer64)%64
partLen=64-index
inputLen=len(ordchrLst)
self.count[0]+=inputLen<<3 #bytes -->bits
if self.count[0] < inputLen:
self.count[1]+=1
self.count[1]+=inputLen>>29
#pading self.buffer64
if len(ordchrLst)>=partLen:
self.buffer64.extend(ordchrLst[:partLen])
ordchrLst=ordchrLst[partLen:]
self.md5Transform(self.buffer64)
self.buffer64=[]
loopN=int(len(ordchrLst)/64)
for idx in range(loopN):
self.md5Transform(ordchrLst[:64])
ordchrLst=ordchrLst[64:]
self.buffer64.extend(ordchrLst)
else:
self.buffer64.extend(ordchrLst)
四、NC了解
Netcat is a simple Unix utility which reads and writes data across network connections, using TCP or UDP protocol.
In the simplest usage, "nc host port" creates a TCP connection to the given port on the given target host. Your standard input is then sent to the host, and anything that comes back across the connection is sent to your standard output. This continues indefinitely, until the network side of the connection shuts down. Note that this behavior is different from most other applications which shut everything down and exit after an end-of-file on the standard input.
六、溢出点测试
6.1程序正常测试
$gdb 567504000c6d6
(gdb) r
Starting program: /root/python/now/567504000c6d6
welcome to Beijing
Pls input the user name : root
Pls input the password : admin
Pls input the information: fsociety
[Inferior 1 (process 8138) exited normally] //程序正常结束状态
6.2 超长文本溢出测试
当文本长度为68*4字节时,产生堆栈溢出异常,可根据此特点,构造shellcode代码,通过恶意程序获取shell,控制过程服务器
>>> '\x00'*68 #python shell
(gdb) r
Starting program: /root/python/now/567504000c6d6
welcome to Beijing
Pls input the user name : o
Pls input the password : o
Pls input the information: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
Program received signal SIGSEGV, Segmentation fault. //程序异常结束,说明堆栈出现异常,刚好验证了溢出漏洞
0x3030785c in ?? () //堆栈
(gdb)
#!/usr/bin/env python3
# coding: utf-8
# 2016-01-06 23:08:46
# Be care of BE LE
from hashlib import md5
from ctypes import c_uint32
from sys import exit
DELTA = 0x9e3779b9
BLOCK_SIZE = 2 # number of 32-bit ints
KEY_SIZE = 4
ROUNDS = 32
SUMATION = 0xc6ef3720
def encrypt_block(block, key, verbose=False):
''' Encrypt a single 64-bit block with a 128-bit key
@param block: list of two c_uint32s
@param key: list of four c_uint32s
'''
assert len(block) == BLOCK_SIZE
assert len(key) == KEY_SIZE
s = c_uint32(0)
delta = c_uint32(DELTA)
for idx in range(ROUNDS):
s.value += delta.value
block[0].value += \
((block[1].value << 4) + key[0].value) ^ \
(block[1].value + s.value) ^\
((block[1].value >> 5) + key[1].value)
block[1].value += \
((block[0].value << 4) + key[2].value) ^\
(block[0].value + s.value) ^\
((block[0].value >> 5) + key[3].value)
if verbose:
print('\t --> Encrypting block round %d of %d' % (idx + 1, ROUNDS))
return block
def decrypt_block(block, key, verbose=False):
'''Decrypt a single 64-bit block with 128-bit key
@param block: list of two c_uint32s
@param key: list of four c_uint32s
'''
assert len(block) == BLOCK_SIZE
assert len(key) == KEY_SIZE
s = c_uint32(SUMATION)
delta = c_uint32(DELTA)
for idx in range(ROUNDS):
block[1].value -=\
((block[0].value << 4) + key[2].value) ^\
(block[0].value + s.value) ^\
((block[0].value >> 5) + key[3].value)
block[0].value -=\
((block[1].value << 4) + key[0].value) ^\
(block[1].value + s.value) ^\
((block[1].value >> 5) + key[1].value)
s.value -= delta.value
if verbose:
print('\t<-- Decrypting block round %d of %d' % (idx +1, ROUNDS))
return block
def to_c_array(string):
'''Convert a string to a list of c_uint32s'''
c_array = []
for idx in range(0, len(string), 8):
x = int(string[idx:idx+8], 16)
# convert BE to LE
x = ((x >> 24) & 0xff) | ((x >> 16) & 0xff) << 8 |\
((x >> 8) & 0xff) << 16 | (x&0xff) << 24
c_array.append(c_uint32(x))
return c_array
def to_string(c_array):
'''Converts a list of c_uint32s to a Python (ascii) string'''
tmp = []
for idx in range(len(c_array)):
x = c_array[idx].value
x = ((x >> 24) & 0xff) | ((x >> 16) & 0xff) << 8 |\
((x >> 8) & 0xff) << 16 | (x&0xff) << 24
tmp.append(x)
output = ''
for block in tmp:
output += hex(block)[2:].zfill(8)
return output.upper()
def xor(c_arrayX, c_arrayY):
'''every bits of c_arrayX xor per c_arrayY's
@param c_arrayX: list of two c_uint32s
@param c_arrayY: list of two c_uint32s
output: bytes list
'''
output = []
for idx in range(2):
x = c_arrayX[idx].value
y = c_arrayY[idx].value
output.append(c_uint32((x & 0xff) ^ (y & 0xff) |\
(((x>>8)&0xff) ^ ((y>>8)&0xff)) << 8 |\
(((x>>16)&0xff) ^ ((y>>16)&0xff)) << 16 |\
(((x>>24)&0xff) ^ ((y>>24)&0xff)) << 24))
return output
def main():
name = input('usr: ').strip()
assert len(name) != 0
m = md5()
m.update(name.encode('ascii'))
k = to_c_array(m.hexdigest())
v = [k[2], k[3]]
v = xor(v, k)
v = decrypt_block(v, k)
print(to_string(v))
#return to_string(v)
#!/usr/bin/env python3
# coding: utf-8
# 2016-01-06 23:08:46
# Be care of BE LE
from hashlib import md5
from ctypes import c_uint32
from sys import exit
DELTA = 0x9e3779b9
BLOCK_SIZE = 2 # number of 32-bit ints
KEY_SIZE = 4
ROUNDS = 32
SUMATION = 0xc6ef3720
def encrypt_block(block, key, verbose=False):
''' Encrypt a single 64-bit block with a 128-bit key
@param block: list of two c_uint32s
@param key: list of four c_uint32s
'''
assert len(block) == BLOCK_SIZE
assert len(key) == KEY_SIZE
s = c_uint32(0)
delta = c_uint32(DELTA)
for idx in range(ROUNDS):
s.value += delta.value
block[0].value += \
((block[1].value << 4) + key[0].value) ^ \
(block[1].value + s.value) ^\
((block[1].value >> 5) + key[1].value)
block[1].value += \
((block[0].value << 4) + key[2].value) ^\
(block[0].value + s.value) ^\
((block[0].value >> 5) + key[3].value)
if verbose:
print('\t --> Encrypting block round %d of %d' % (idx + 1, ROUNDS))
return block
def decrypt_block(block, key, verbose=False):
'''Decrypt a single 64-bit block with 128-bit key
@param block: list of two c_uint32s
@param key: list of four c_uint32s
'''
assert len(block) == BLOCK_SIZE
assert len(key) == KEY_SIZE
s = c_uint32(SUMATION)
delta = c_uint32(DELTA)
for idx in range(ROUNDS):
block[1].value -=\
((block[0].value << 4) + key[2].value) ^\
(block[0].value + s.value) ^\
((block[0].value >> 5) + key[3].value)
block[0].value -=\
((block[1].value << 4) + key[0].value) ^\
(block[1].value + s.value) ^\
((block[1].value >> 5) + key[1].value)
s.value -= delta.value
if verbose:
print('\t<-- Decrypting block round %d of %d' % (idx +1, ROUNDS))
return block
def to_c_array(string):
'''Convert a string to a list of c_uint32s'''
c_array = []
for idx in range(0, len(string), 8):
x = int(string[idx:idx+8], 16)
# convert BE to LE
x = ((x >> 24) & 0xff) | ((x >> 16) & 0xff) << 8 |\
((x >> 8) & 0xff) << 16 | (x&0xff) << 24
c_array.append(c_uint32(x))
return c_array
def to_string(c_array):
'''Converts a list of c_uint32s to a Python (ascii) string'''
tmp = []
for idx in range(len(c_array)):
x = c_array[idx].value
x = ((x >> 24) & 0xff) | ((x >> 16) & 0xff) << 8 |\
((x >> 8) & 0xff) << 16 | (x&0xff) << 24
tmp.append(x)
output = ''
for block in tmp:
output += hex(block)[2:].zfill(8)
return output.upper()
def xor(c_arrayX, c_arrayY):
'''every bits of c_arrayX xor per c_arrayY's
@param c_arrayX: list of two c_uint32s
@param c_arrayY: list of two c_uint32s
output: bytes list
'''
output = []
for idx in range(2):
x = c_arrayX[idx].value
y = c_arrayY[idx].value
output.append(c_uint32((x & 0xff) ^ (y & 0xff) |\
(((x>>8)&0xff) ^ ((y>>8)&0xff)) << 8 |\
(((x>>16)&0xff) ^ ((y>>16)&0xff)) << 16 |\
(((x>>24)&0xff) ^ ((y>>24)&0xff)) << 24))
return output
def main():
name = input('usr: ').strip()
assert len(name) != 0
m = md5()
m.update(name.encode('ascii'))
k = to_c_array(m.hexdigest())
v = [k[2], k[3]]
v = xor(v, k)
v = decrypt_block(v, k)
print(to_string(v))
#return to_string(v)
import string
from binascii import unhexlify
from hashlib import md5
# ollydbg 内存数据分析函数,注意,OD 中的数据以 little-endian 形式显示
s = '''20 DE 87 7D AB 1F 7A 0E'''
def rev(s):
s = s.split()
s = ['0x' + i for i in s]
s = str(s).replace("'", '')
print(s)
def ishex(s):
assert type(s) is str
hex_digits = set(string.hexdigits)
return all(c in hex_digits for c in s)
###############################################
from xmath import mulinv
from cryptocommon import ascii_to_int
def rsa_keygen(name, p, q, e):
c = ascii_to_int(name)
n = p * q
phi = (p - 1) * (q - 1)
d = mulinv(e, phi)
m = pow(c, d, n)
return hex(m)[2:].upper()
if __name__ == '__main__':
name = input('name : ')
e = 0x10001
n = 0x80C07AFC9D25404D6555B9ACF3567CF1
# p, q is decomposition by rsa-tool2 by TE
p = 0xA554665CC62120D3
q = 0xC75CB54BEDFA30AB
print('serial: {}'.format(rsa_keygen(name, p, q, e)))