from random import randint, getrandbits
from math import gcd
from xmath import mulinv, xgcd, xpow
from isprime import genprime
def elgamal_sig_init(size):
'''
@size: int, size > msg
y = a^x mod q
it's difficult to find random prime root 'a'
'''
x = q = genprime(size)
a = randint(2, q - 2)
size = q.bit_length()
while x >= q:
x = getrandbits(size)
y = pow(a, x, q)
return (q, a, x, y)
def elgamal_sig(m):
'''
@m: int, msg < q
s1 = a^k mod q
M = (x*s1 + k * s2) mod (q - 1) -> s2
pub_key -> (a, q, y)
pri_key -> x
signature -> (s1, s2)
'''
q, a, x, y = elgamal_sig_init()
k = randint(2, q -2)
while gcd(k, q - 1) != 1:
k = randint(2, q - 2)
s1 = pow(a, k, q)
k_inv = mulinv(k, q - 1)
s2 = k_inv * (m - x * s1) % (q - 1)
return (m, a, q, y, s1, s2)
def elgamal_sig_verify(args):
'''
(y^s1) * (s1^s2) = a^m mod p
'''
m, a, q, y, s1, s2 = args
v1 = pow(a, m, q)
v2 = pow(y, s1, q) * pow(s1, s2, q) % q
return True if v1 == v2 and 1<= a < p else False
def ready(size):
'''
y = g^x mod p
a = g^k mod p
b = y^k mod p
1 < g, k, x < p - 1
pub_key -> (a, b, p)
pri_key -> (a, b, p, x)
'''
x = p = genprime(size)
k = randint(2, p - 2)
while gcd(k, p - 1) != 1:
k = randint(2, p - 2)
g = randint(2, p - 2)
while x >= p:
x = getrandbits(size)
y = pow(g, x, p)
a = pow(g, k, p)
b = pow(y, k, p)
return (a, b, p, x)
# args = ready(n)
def crypto(m, a, b, p):
b = m * b % p
return (a, b)
def decrypt(a, b, p, x):
ax = pow(a, x, p)
inv = mulinv(ax, p)
m = b * inv % p
return m
if __name__ == '__main__':
# m < 0xCE892335578D3F
m = 1124
sig = elgamal_sig(m)
print(sig)
print(elgamal_sig_verify(sig))
# genprime
from random import randint
from random import getrandbits
def find_kq(n):
q = n - 1
k = 1
while not (q & 1):
q >>= 1
k += 1
return k , q
# n > 2
def isprime(n):
assert n > 2
if n & 1 == 0:
return False
k, q = find_kq(n)
a = randint(1, n - 1)
if pow(a, q, n) == 1: # 优化 a ** q % n
return True
for j in range(k):
if pow(a, pow(2, j) * q, n) == n - 1: # a **((2 ** j) * q) % n
return True
return False
# RSA 推荐 bit_length = 1024, 约6.84s 生成一个素数, 2048 约 15s, 平均测试 log(2**1024,e)//2 = 70次
def genprime(bit_length):
while True:
x = getrandbits(bit_length) # 比 randint() 快3.9倍以上
if isprime(x):
return x
# mulinv
# return (g, x, y) a*x + b*y = gcd(x, y)
def xgcd(b, n):
x0, x1, y0, y1 = 1, 0, 0, 1
while n != 0:
q, b, n = b // n, n, b % n
x0, x1 = x1, x0 - q * x1
y0, y1 = y1, y0 - q * y1
return (b, x0, y0)
# x = mulinv(b) mod n
def mulinv(b, n):
g, x, _ = xgcd(b, n)
if g == 1:
return x % n
def check(name, serial):
# type(name) == type(serial) == str
assert True if name and serial else False, 'Wrong Serial !'
if '-' not in serial:
return False
m = md5()
m.update(b'ped')
m.update(name.encode('ascii'))
szHash =m.hexdigest()
M = int(szHash, 16)
# 4DB4A765FD4F0809A881A78966456945
szSerial = serial.split('-')
try:
a, b= [int(i, 16) for i in szSerial]
except:
print('Wrong Serial !')
return False
p = 0xCE892335578D3F
g = 0x473FE7D24CB6A6
y = 0xA3CCD85BBD896
result1 = pow(y, a, p)
result2 = pow(a, b, p)
result3 = result1 * result2 % p
result4 = pow(g, M, p)
if result4 == result3:
print('success')
return True
else:
print('Wrong Serial !')
return False
if __name__ == '__main__':
name = 'ipediy'
serial = 'ACD47530E2ED99-295158D2AAA31B'
check(name, serial) # True
from sys import version
from random import randint
from hashlib import md5
from binascii import hexlify
from math import gcd
from xmath import mulinv
if 'v2.7' in version:
input = raw_input
def keygen(name):
assert type(name) is str
p = 0xCE892335578D3F
g = 0x473FE7D24CB6A6
y = 0xA3CCD85BBD896
x = 0x264D8D82C7AAB8
k = randint(2, p -2)
m = md5()
m.update(b'ped')
m.update(name.encode('ascii'))
szHash =m.hexdigest()
M = int(szHash, 16)
while gcd(k, p - 1) != 1:
k = randint(2, p - 2)
s1 = pow(g, k, p)
k_inv = mulinv(k, p - 1)
s2 = k_inv * (M - x * s1) % (p - 1)
serial = hex(s1)[2:].upper() + '-' + hex(s2)[2:].upper()
return serial
def check(name, serial):
# type(name) == type(serial) == str
assert True if name and serial else False, 'Wrong Serial !'
if '-' not in serial:
return False
m = md5()
m.update(b'ped')
m.update(name.encode('ascii'))
szHash =m.hexdigest()
M = int(szHash, 16)
# 4DB4A765FD4F0809A881A78966456945
szSerial = serial.split('-')
try:
a, b= [int(i, 16) for i in szSerial]
except:
print('Wrong Serial !')
return False
p = 0xCE892335578D3F
g = 0x473FE7D24CB6A6
y = 0xA3CCD85BBD896
result1 = pow(y, a, p)
result2 = pow(a, b, p)
result3 = result1 * result2 % p
result4 = pow(g, M, p)
if result4 == result3:
print('success')
return True
else:
print('Wrong Serial !')
return False
if __name__ == '__main__':
name = 'ipediy'
serial = 'ACD47530E2ED99-295158D2AAA31B'
check(name, serial) # True
# RDLP Tools v1.12 y = g^x mod p --> x = 0x264D8D82C7AAB8 614s(Try 486711703 cnts)
while True:
s = keygen(input('name > '))
print('serial > {}'.format(s))
'''output
name > pediy
serial > 9390FD5DA9F5F-7F98F18EEDEE21
name > pediy
serial > 9494C8510B670D-C440133310FD6B
name > pediy
serial > 45C7449F72112D-4B0ED5382A89D5
name > pediy
serial > B1B6C76E5EF311-13CCA372E41A3B
'''
#!/usr/bin/env python
# coding: utf-8
# 2016.5.27 19:31
from random import randint, getrandbits
from xmath import mulinv
from isprime import genprime
def modular_sqrt(a, p):
""" Find a quadratic residue (mod p) of 'a'. p
must be an odd prime.
Solve the congruence of the form:
x^2 = a (mod p)
And returns x. Note that p - x is also a root.
0 is returned is no square root exists for
these a and p.
The Tonelli-Shanks algorithm is used (except
for some simple cases in which the solution
is known from an identity). This algorithm
runs in polynomial time (unless the
generalized Riemann hypothesis is false).
"""
# Simple cases
#
if legendre_symbol(a, p) != 1:
return 0
elif a == 0:
return 0
elif p == 2:
return p
elif p % 4 == 3:
return pow(a, (p + 1) // 4, p)
# Partition p-1 to s * 2^e for an odd s (i.e.
# reduce all the powers of 2 from p-1)
#
s = p - 1
e = 0
while s % 2 == 0:
s //= 2
e += 1
# Find some 'n' with a legendre symbol n|p = -1.
# Shouldn't take long.
#
n = 2
while legendre_symbol(n, p) != -1:
n += 1
# Here be dragons!
# Read the paper "Square roots from 1; 24, 51,
# 10 to Dan Shanks" by Ezra Brown for more
# information
#
# x is a guess of the square root that gets better
# with each iteration.
# b is the "fudge factor" - by how much we're off
# with the guess. The invariant x^2 = ab (mod p)
# is maintained throughout the loop.
# g is used for successive powers of n to update
# both a and b
# r is the exponent - decreases with each update
#
x = pow(a, (s + 1) // 2, p)
b = pow(a, s, p)
g = pow(n, s, p)
r = e
while True:
t = b
m = 0
for m in range(r):
if t == 1:
break
t = pow(t, 2, p)
if m == 0:
return x
gs = pow(g, 2 ** (r - m - 1), p) # wiki var(b)
g = (gs * gs) % p # wiki var(c`)
x = (x * gs) % p # x^2 = a*t mod p, if t == 1 then x is square root
b = (b * g) % p # wiki var(t`)
r = m # x -> wiki var(r`), r -> wiki var(j)
def legendre_symbol(a, p):
""" Compute the Legendre symbol a|p using
Euler's criterion. p is a prime, a is
relatively prime to p (if p divides
a, then a|p = 0)
Returns 1 if a has a square root modulo
p, -1 otherwise.
"""
ls = pow(a, (p - 1) // 2, p)
return -1 if ls == p - 1 else ls
def nfa(n):
size = n.bit_length()
o = [(n >> i) & 1 for i in range(size - 1, -1, -1)]
o.insert(0, 0)
j = 0
for i in range(size - 1, -1, -1):
if o[i] == o[i + 1] == 1:
j += 1
continue
if j != 0:
o[i: i + j + 2] = [1] + [0] * j + [-1]
j = 0
return o
class ECC(object):
'''
ECC(size [, p, B, A])
ECC(0, p [, B, A])
p.bit_length() == 256, (p, B) will be randomly generated
>>> c = ECC(size = 256) # p.bit_length() == 256, (p, B) will be randomly generated
A = -3 by default, also you can specify another value
>>> c = ECC(p=23, B=17, A=9) # y^2 = x^3 + Ax + B (mod p)
>>> P = (16, 5)
Caution: Not all points(x, y) on elliptic curves, x belogs to Zp
>>> Q = (20, c.gety(20)[0]) # gety(x) -> (y1, y2) or False
>>> Q == (20, 3)
>>> (16, 18) == c.eccplus(P, Q)
>>> (7, 3) == c.eccmul(6, P)
'''
def __init__(self, size=0, p=0, B=0, A=-3):
assert (size == p == 0) is False, 'ECC(size, p, B, A) -> size must give'
self.size = size # size bits
self.p = p
self.B = B
if self.p == 0:
while True:
p = genprime(size)
if p % 4 == 3:
self.p = p
break
self.A = A % p
if self.B == 0:
self.getab()
else:
self.checkab()
if self.size == 0:
self.size = p.bit_length()
def getab(self):
A = self.A
p = self.p
while True:
# a, b belong to Z_p
B = randint(0, p)
# be confirm as a abelian group
if (4 * A ** 3 + 27 * B ** 2) % p != 0:
self.B = B
break
def checkab(self):
if (4 * self.A ** 3 + 27 * self.B ** 2) % self.p == 0:
raise ValueError('A, B is invalid, try another!')
def getdistlaw(self):
''' get quadratic residue distribution law of mod(p)'''
p = self.p
if p == 2:
return 0
return (p - 1) // 2
def gety(self, x):
A = self.A
B = self.B
p = self.p
a = (x ** 3 + A * x + B) % p
y1 = modular_sqrt(a, p)
if y1 == 0:
return False
y2 = -y1 % p
return y1, y2
def eccplus(self, P, Q):
try:
assert type(P) is type(Q) is tuple and len(P) == len(Q) == 2
except AssertionError:
print('eccplus(P, Q) -> P or Q must be (x, y) tuple')
return False
p = self.p
x1, y1 = P
x2, y2 = Q
if P == (0, 0) or Q == (0, 0):
return (x1 + x2, y1 + y2)
if x1 == x2 and y1 == -y2 % p:
return 0, 0
if P != Q:
_lambda = ((y2 - y1) * mulinv(x2 - x1, p)) % p
else:
_lambda = (3 * x1 * x1 + self.A) * mulinv(2 * y1, p) % p
x3 = (_lambda * _lambda - x1 - x2) % p
y3 = (_lambda * (x1 - x3) - y1) % p
return (x3, y3)
def eccmul2(self, n, P):
# n * P
try:
assert type(n) is int and type(P) is tuple and len(P) == 2
except AssertionError:
print('eccmul(n, P), n must be int, P must be (x, y) tuple')
return False
if n <= 0:
return 0, 0
x3, y3 = P
for i in range(n - 1):
x3, y3 = self.eccplus(P , (x3, y3))
return x3, y3 # Q = nP
def eccmul(self, n, P):
# double_and algorithm
o = nfa(n)
Q = (0, 0)
for c in o:
Q = self.eccplus(Q, Q)
if c == 1:
Q = self.eccplus(Q, P)
elif c == -1:
Q = self.eccplus(Q, (P[0], -P[1]))
return Q
class ECIES(ECC):
def __init__(self, args=None, A=0, B=0, p=0):
'''
o = ECIES() # ECIES(size=160)
o = ECIES(224) # ECIES(size=224) init for enrypt
o = ECIES(prikey, pubkey) # init for decrypt
o = ECIES(pubkey) # init for encrypt
o = ECIES(prikey) # init for decrypt
'''
if A & B & p != 0:
super(ECIES, self).__init__(A=A, B=B, p=p)
self.init()
elif args == None:
super(ECIES, self).__init__(size=160)
self.init()
elif type(args) == int:
super(ECIES, self).__init__(size=args)
elif len(args) == 2 and type(args[1]) == int:
prikey = args
p, A, B, P = prikey[0]
self.d = prikey[1]
super(ECIES, self).__init__(p=p, A=A, B=B)
elif len(args) == 2 and len(args[1]) == 2 and type(args[1][1]) == int:
pubkey = args
p, A, B, P = pubkey[0]
super(ECIES, self).__init__(p=p, A=A, B=B)
self.Q = pubkey[1]
elif len(args) == 2 and len(args[1]) == 2 and \
type(args[1][1]) == tuple and \
len(args[1][1]) == 2:
prikey, pubkey = args
p, A, B, P = pubkey[0]
super(ECIES, self).__init__(p=p, A=A, B=B)
self.Q = pubkey[1]
self.d = prikey[1]
else:
raise ValueError('ECIES({}'.format(args))
def sha(self, x):
from hashlib import sha1
sha = sha1()
if type(x) == str:
x = x.encode('ascii')
sha.update(x)
e = int(sha.hexdigest(), 16) % self.n
return e
def sign(self, x):
self.getkey()
k = getrandbits(self.size) % self.n
kP = self.eccmul(k, self.P)
r = kP[0] % self.n
if (k & r) == 0:
return self.sign(x)
e = self.sha(x)
s = (mulinv(k, self.n) * (e + self.d * r)) % self.n
if s == 0:
return self.sign(x)
pubkey = (self.common, self.Q)
return pubkey, (r, s)
def verify(self, x, r, s):
if not (1 <= r <= self.n -1 and 1 <= s <= self.n -1):
return False
e = self.sha(x)
inv_s = mulinv(s, self.n)
u1 = (e * inv_s) % self.n
u2 = (r * inv_s) % self.n
u1P = self.eccmul(u1, self.P)
# bug: (r * inv_s % n) * Q != (r * inv_s * d % n) * P
# debug: self.n must be carefully choose
u2Q = self.eccmul(u2, self.Q)
X = self.eccplus(u1P, u2Q)
if X == (0, 0):
return False
v = X[0] % self.n
return v == r
if __name__ == '__main__':
import ipdb
x = b'I love you'
ss = ECDSA()
ipdb.set_trace()
common = ss.sign(x)
o = ECDSA(common[0])
r, s = common[1]
print(o.verify(x, r, s))
o = ECIES()
o.init()
y = o.crypto(100)
print(y)
print(o.decrypt(y))
c = ECC(p=23, B=17, A=9)
P = (16, 5)
print('y^2 = x^3 + 9x + 17 mod 23, P = {}'.format(str(P)))
for i in range(1, 10):
print('{}P = {}'.format(i, str(c.eccmul(i, P))))
def fgint(data):
assert type(data) is int
_ord = 0x80000000 # 2^31
(x, r) = divmod(data, _ord)
rLst = [r]
while x != 0:
(x, r) = divmod(x, _ord)
rLst.append(r)
rLst.insert(0, len(rLst))
rLst = [BE2LE(r) for r in rLst]
rLst = [hex(r)[2:].zfill(8).upper() for r in rLst]
return ' '.join(rLst)
if __name__ == '__main__':
s = "322334816268407046326335149654703840583"
print(fgint(int(s)))
IDEAKeyGenMe.c key function
void key(unsigned short uskey[9], unsigned short Z[7][10])
{
unsigned short S[54];
int i, j, r;
for(i = 1; i<9; i++)
S[i-1] = uskey[i];
def get_serial(name):
m = sha1()
m.update(name.encode('ascii'))
h = list(m.digest())
volC = vol()
c = h[-4:] + volC
c = endian16(c)
key = endian16(h[0: 16])
serial = decrypt(c, key)
return ''.join([hex(i)[2:].zfill(2) for i in serial]).upper()
def byte_xor(x, y):
# x,y -> bytes list
assert type(x) == type(y) == list
assert len(x) == len(y)
z = []
for i in range(len(x)):
z.append(x[i] ^ y[i])
return z
if __name__ == '__main__':
# import ipdb
# ipdb.set_trace()
while True:
print(get_serial())
input()
----------------------------------------------------
python辅助 逆向分析过程
# 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)
################################
serial = '0123456789abcdef0123456789abcdef'
assert len(serial) == 32
from binascii import unhexlify
xSeri = list(unhexlify(serial))
# 01 23 45 67 89 AB CD EF 01 23 45 67 89 AB CD EF
def verify(name, serial):
''' VB P-code 逻辑再现
name = cyclotron => S1 = 9912199108111116114111110
'''
name = name.strip()
serial = serial.strip()
assert name != '' and serial != '', 'Both name and serial need!'
S1 = int(''.join([str(ord(i)) for i in name]))
pi = 3.141592654
while len(str(S1)) > 9:
S1 = int(S1 / pi)
S2 = (S1 ^ 0x30f85678) - 0xd8b3
if len(name) == int(serial) - S2:
print('The register is right!')
else:
print('Try again!')
def genSerial(name):
name = name.strip()
assert len(name) != 0
S1 = int(''.join([str(ord(i)) for i in name]))
while len(str(S1)) > 9:
S1 = int(S1 / 3.141592654)
S2 = (S1 ^ 0x30f85678) - 0xd8b3
return len(name) + S2
if __name__ == '__main__':
verify('cyclotron', '667574641')
print(genSerial('cyclotron'))
PEBrowserDbg 官方下载地址:http://www.smidgeonsoft.prohosting.com/pebrowse-pro-interactive-debugger.html
官方提供以下两个版本的动态调试工具:
PEBrowseDbg64 Interactive.
for Windows 7, Windows 8 and Windows 10 (all versions 64-bit only)
PEBrowse Professional Interactive.
for Windows 2000/XP/2003/Vista32/Windows 7
PEBrowseDbg64 首次运行需要配置环境变量,方法如下:
设置系统环境变量
_NT_SYMBOL_PATH
srv*C:\Symbols*http://msdl.microsoft.com/download/symbols
如果不设置,程序会出现以下提示
“The environment variable _NT_SYMBOL_PATH was not found”