Skip to content
This repository has been archived by the owner on Aug 29, 2021. It is now read-only.

Commit

Permalink
make wvguesser faster
Browse files Browse the repository at this point in the history
  • Loading branch information
xhlove committed Jul 30, 2021
1 parent c0cb3e4 commit 0e5b494
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 21 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@

## 本地破解

如果是exe版本,直接将`offline_config.json`拖到`wvguesser_v1.1.0.exe`上即可
如果是exe版本,直接将`offline_config.json`拖到`wvguesser_v1.2.0.exe`上即可

运行程序,等待解密

- `python -m wvguesser.mainv2`

根据现有算法,只能是单线程

演示
效果演示,3600X三分钟左右出结果

![](/images/oCam_2021_07_30_20_58_41_915.gif)
![](/images/oCam_2021_07_31_05_10_50_756.gif)

# main.exe

Expand All @@ -39,7 +39,7 @@ g++ -o main -pthread -std=gnu++0x -static main.cpp misc.cpp codelift.cpp algebra
# 打包

```bash
pyinstaller -n wvguesser_v1.1.0 -F wvguesser\__main__.py
pyinstaller -n wvguesser_v1.2.0 -F wvguesser\__main__.py
```

# 推荐更好的方案
Expand Down
2 changes: 1 addition & 1 deletion guesskey/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ int main(int argc,char **argv)
std::string::size_type sz;
int port = std::stoi(argv[1], &sz);
cout << "listen at:" << port << endl;
SocketServer in(port, 5);
SocketServer in(port, 10);
while (1) {
Socket* s=in.Accept();
unsigned ret;
Expand Down
Binary file removed images/oCam_2021_07_30_20_58_41_915.gif
Binary file not shown.
Binary file added images/oCam_2021_07_31_05_10_50_756.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified main.exe
Binary file not shown.
106 changes: 90 additions & 16 deletions wvguesser/mainv2.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,110 @@
import socket
import binascii
import subprocess
from typing import List
from concurrent.futures import ThreadPoolExecutor
from pathlib import Path
from random import randint
from Crypto.Cipher import AES
from Crypto.Hash import CMAC


port = randint(20000, 50000)
MAIN_EXE = (Path('.') / 'main.exe').resolve().as_posix()
p = subprocess.Popen(f'{MAIN_EXE} {port}', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
time.sleep(1)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('127.0.0.1', port))
servers = []
clients = []
for i in range(5):
port = randint(20000, 50000)
MAIN_EXE = (Path('.') / 'main.exe').resolve().as_posix()
p = subprocess.Popen(f'{MAIN_EXE} {port}', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
servers.append(p)
time.sleep(0.3)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('127.0.0.1', port))
clients.append(client)


def handle_exit(signum, frame):
p.kill()
close()


def call_func(msg: bytes):
client.send(msg.encode("utf-8"))
def close():
try:
[p.close() for p in clients]
[p.kill() for p in servers]
except Exception:
pass


def call_func(client, msg: bytes):
client.send(msg)
resp = client.recv(1024)
return resp.decode('utf-8').strip()


def guessInput(text: str):
return call_func(f'guessInput|{text}\n')
def multi_guessInput(bufs: List[bytes]):
results = []
with ThreadPoolExecutor(max_workers=5) as executor:
results = executor.map(guessInput, clients, bufs)
return results


def guessInput(client, buf: bytes):
# return call_func(client, f'guessInput|{buf}\n')
return call_func(client, b'guessInput|' + buf + b'\n')


def getDeoaep(client, buf: bytes):
# return call_func(client, f'getDeoaep|{buf}\n')
return call_func(client, b'getDeoaep|' + buf + b'\n')


def getDeoaep(text: str):
return call_func(f'getDeoaep|{text}\n')
def runv2(hex_session_key: str):
ts = time.time()
encKey = binascii.a2b_hex(hex_session_key)
print(hex_session_key)
buf = [0] * 1026
offset = 2
while offset < 1026:
print(f'[Progress] {(offset - 2) / 1024 * 100:.2f}% time used {time.time() - ts:.2f}s')
bt = math.floor((offset - 2) / 4)
offs = math.floor((offset - 2) % 4)
desired = (encKey[len(encKey) - bt - 1] >> (offs * 2)) & 3
destail = hex_session_key[len(hex_session_key) - bt * 2:len(hex_session_key)]
bufs = []
j = buf[offset]
for _j in range(5):
buf[offset] = _j
bufs.append(binascii.b2a_hex(bytes(buf)))
for _j, val in enumerate(multi_guessInput(bufs)):
sub = int(val[len(val) - bt * 2 - 2:len(val) - bt * 2], 16)
got = (sub >> (offs * 2)) & 3
gtail = val[len(hex_session_key) - bt * 2:len(hex_session_key) + bt * 2]
if got == desired and gtail == destail:
buf[offset] = _j
j = buf[offset]
break
if j == 8:
buf[offset] = 0
offset -= 1
if offset < 2:
print('Could not match input')
assert 1 == 0, "Could not find proper input encoding"
buf[offset] += 1
while buf[offset] == 8:
buf[offset] = 0
offset -= 1
if offset < 2:
print('Could not match input')
assert 1 == 0, "Could not find proper input encoding"
buf[offset] += 1
else:
offset += 1
print(f'==> time used {time.time() - ts:.2f}s')
print("Output", buf)
outp = getDeoaep(clients[0], binascii.b2a_hex(bytes(buf)))
print(outp)
if len(outp) < 10:
assert 1 == 0, 'Could not remove padding, probably invalid key'
return outp


def run(hex_session_key: str):
Expand Down Expand Up @@ -87,7 +161,6 @@ def run(hex_session_key: str):
if len(outp) < 10:
assert 1 == 0, 'Could not remove padding, probably invalid key'
print(st)
p.kill()
return outp


Expand All @@ -110,9 +183,10 @@ def main():
if len(sys.argv) == 2:
path = sys.argv[1]
else:
path = (Path('.') / 'offline_config_yk.json').resolve().as_posix()
path = (Path('.') / 'offline_config.json').resolve().as_posix()
config = json.loads(Path(path).read_text(encoding='utf-8'))
clear_session_key = run(config['enc_session_key'])
clear_session_key = runv2(config['enc_session_key'])
close()
decrypt_license_keys(clear_session_key, config['enc_key'], config['key_infos'])
sys.stdin.read()

Expand Down

0 comments on commit 0e5b494

Please sign in to comment.