Гайд Нормальный клиент с привязкой по железу на питоне

Пользователь
Статус
Оффлайн
Регистрация
21 Апр 2017
Сообщения
57
Реакции[?]
32
Поинты[?]
0
Увидев одну из тем, я понял что этот мир уже не спасти от наплывающих питонистов, поэтому решил показать как надо делать.

Так как у нас будет нормальный код и шифрование данных, мы будем использовать алгоритм RSA.
Нам нужно будет сгенерировать 2 пары, одна для сервер-клиент, вторая для клиент-сервер.
Вместо 1024 можно указать любой размер, чем больше, тем дольше будет работать генерация и алгоритм.
Python:
pubkey, privkey = rsa.newkeys(1024)  # генерируем пару ключей
pickle.dump(privkey, open('key.key', 'wb+'))  # сохраняем ключ в файл
Теперь напишем клиент
Python:
import requests
import datetime
import hashlib
import pickle
import uuid
import json
import rsa


def get_hwid() -> str:
    hwid = str(uuid.uuid1(uuid.getnode(), 0))[24:]

    hwid_hash = hashlib.sha256(hwid.encode('utf-8'))

    return hwid_hash.hexdigest()


def post(url: str, data: dict) -> dict:
    client_public_key = pickle.load(open('client_public.key', 'rb'))
    server_private_key = pickle.load(open('server_private.key', 'rb'))

    encoded = rsa.encrypt(json.dumps(data).encode('utf-8'), client_public_key).hex()
    data = {'data': encoded}

    response = requests.post(url, data=data)

    data = response.json()['data']
    decoded = rsa.decrypt(bytes.fromhex(data), server_private_key).decode('utf-8')

    return json.loads(decoded)


def get_license(hwid: str) -> bool:
    data = post('http://localhost:5000/get_license', {'hwid': hwid})
    lic = data['license']

    return datetime.datetime.fromtimestamp(lic) > datetime.datetime.now()


hwid = get_hwid()
lic = get_license(hwid)
А тут будет код сервера, я буду использовать sqlite3 для простоты, кому надо будет перепишет на норм субд
Python:
from flask import Flask, request
import datetime
import sqlite3
import pickle
import json
import rsa

client_private_key = pickle.load(open('client_private.key', 'rb'))
server_public_key = pickle.load(open('server_public.key', 'rb'))


class Database:
    def __init__(self, db_name: str):
        self.db_name = db_name

        self.initialize()

    def initialize(self):
        connection = self.get_connection()
        cursor = connection.cursor()

        cursor.execute('CREATE TABLE IF NOT EXISTS users('
                       'id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,'
                       'hwid VARCHAR(64),'
                       'license REAL)')
        connection.commit()

        cursor.close()
        connection.close()

    def get_connection(self):
        return sqlite3.connect(self.db_name)

    def get_license(self, hwid: str) -> datetime.datetime:
        connection = self.get_connection()
        cursor = connection.cursor()

        cursor.execute(f"SELECT license FROM users WHERE hwid='{hwid}'")

        (result,) = cursor.fetchone()

        cursor.close()
        connection.close()

        return datetime.datetime.fromtimestamp(result)

    def update_license(self, hwid: str, date: datetime.datetime) -> None:
        connection = self.get_connection()
        cursor = connection.cursor()

        cursor.execute(f"UPDATE users SET license={date.timestamp()} WHERE hwid='{hwid}'")
        connection.commit()

        cursor.close()
        connection.close()

    def set_license(self, hwid: str, date: datetime.datetime) -> None:
        connection = self.get_connection()
        cursor = connection.cursor()

        cursor.execute(f"INSERT INTO users (hwid, license) VALUES ('{hwid}', {date.timestamp()}")
        connection.commit()

        cursor.close()
        connection.close()


db = Database('database.db')
app = Flask(__name__)


@app.route('/get_license', methods=['POST'])
def get_license():
    if request.method == 'POST':
        data = request.form['data']
        data = json.loads(rsa.decrypt(bytes.fromhex(data), client_private_key))

        hwid = data['hwid']
        lic = db.get_license(hwid).timestamp()

        response = rsa.encrypt(json.dumps({'license': lic}).encode('utf-8'), server_public_key).hex()

        return {'data': response}
    return '404'


app.run()

Код есть, но мамкины крякеры, никуда еще не делись, поэтому нам нужно будет защитить код клиента. Мы будем использовать для этого PyArmor, у него есть лишь один недостаток, для защиты большого проекта нужно купить лицензию, но нам сейчас хватит и бесплатной версии.
  • Устанавливаем pyarmor
  • Открываем терминал и переходим в папку нашего клиента
  • Пишем pyarmor pack -e " --onefile" client.py
  • Ждем пока закончится магия
  • В папке dist будет лежать exe файл нашего клиента

Для особо внимательных, кто заметил что наш клиент переродился в исполняемом файле: pyarmor использует pyinstaller для упаковки питонячего кода, но даже если супер-крякер777 доберется до распакованной временной папки нашего клиента и декомпилировав pyc файл, открыв исходник он, к его сожалению, увидит лишь это:
Python:
from pytransform import pyarmor_runtime
pyarmor_runtime()
__pyarmor__(__name__, __file__, b'\x50\x59\x41\x52\x4d\x4f...', 2)

Что в итоге мы сделали?
  • Написали более менее человеческий код
  • Защитили исходник
  • Использовали СУБД!!!!
  • Написали сервер (wow)
 
Эксперт
Статус
Оффлайн
Регистрация
9 Апр 2020
Сообщения
1,367
Реакции[?]
644
Поинты[?]
4K
Чел, это не говно код, удаляй тему !!! :roflanEbalo:
У нас, питонистов, только код какашка
 
Пользователь
Статус
Оффлайн
Регистрация
21 Апр 2017
Сообщения
57
Реакции[?]
32
Поинты[?]
0
а нуда,это же пайтон.Защитили... угу
Да, защитили. Если сомневаешься, можешь почитать доки\глянуть исходный код PyArmor и изучить принцип его работы\попробовать взломать его защиту. Иначе, твой комментарий не несет никакой смысловой нагрузки.
 
Web developer / designer
Пользователь
Статус
Оффлайн
Регистрация
15 Ноя 2020
Сообщения
411
Реакции[?]
124
Поинты[?]
2K
Да, защитили. Если сомневаешься, можешь почитать доки\глянуть исходный код PyArmor и изучить принцип его работы\попробовать взломать его защиту. Иначе, твой комментарий не несет никакой смысловой нагрузки.
забей, он всё ещё думает, что питон можно декомпилировать
 
всем прив верите ли вы в призраков ???
Забаненный
Статус
Оффлайн
Регистрация
17 Авг 2018
Сообщения
863
Реакции[?]
338
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Вот это - server_private_key = pickle.load(open('server_private.key', 'rb')) убивает весь смысл шифровки.
 
Олдфаг
Статус
Оффлайн
Регистрация
18 Фев 2019
Сообщения
2,826
Реакции[?]
1,853
Поинты[?]
24K
Гайд вышел достаточно полезный, но есть пара моментов в коде, которые необходимо изменить. Начнем с того, что использование RSA шифрования в программе просто бесполезно. Взломщику достаточно подменить ответ сервера на данные уже авторизированного пользователя, не занимаясь расшифровкой. Это легко решается введением дополнительных проверок, например, по никнейму или времени ответа сервера.
Также хорошим решением стало бы использование сокетного соединения, вместо простых POST запросов. Это позволит скрыть трафик и значительно усложнить процесс подмены ответов.

Важные поправки для совсем новичков в Python:
1. Перед запуском вашего клиента и сервера необходимо установить все используемые модули с помощью pip. Пропишите pip install -r requirements.txt (файл приложен к сообщению).
2. Код файла с генерацией ключей RSA необходимо заменить на:
Python:
import rsa
import pickle
pubkey, privkey = rsa.newkeys(1024)  # генерируем пару ключей
pickle.dump(privkey, open('client_private.key', 'wb+'))  # сохраняем ключ в файл
pickle.dump(pubkey, open('server_publickey', 'wb+'))  # сохраняем ключ в файл
3. Для работы упаковщика файлов при использовании PyArmor необходимо установить PyInstaller с помощью pip.

Хоть и не существует публичных деобфускаторов PyArmor, я все равно не рекомендую писать серьезные проекты на Python. Посмотрите в сторону C++, если нет желания или возможности проводить все важные проверки и операции на сервере.
 

Вложения

Пользователь
Статус
Оффлайн
Регистрация
21 Апр 2017
Сообщения
57
Реакции[?]
32
Поинты[?]
0
Гайд вышел достаточно полезный, но есть пара моментов в коде, которые необходимо изменить. Начнем с того, что использование RSA шифрования в программе просто бесполезно. Взломщику достаточно подменить ответ сервера на данные уже авторизированного пользователя, не занимаясь расшифровкой. Это легко решается введением дополнительных проверок, например, по никнейму или времени ответа сервера.
Также хорошим решением стало бы использование сокетного соединения, вместо простых POST запросов. Это позволит скрыть трафик и значительно усложнить процесс подмены ответов.

Важные поправки для совсем новичков в Python:
1. Перед запуском вашего клиента и сервера необходимо установить все используемые модули с помощью pip. Пропишите pip install -r requirements.txt (файл приложен к сообщению).
2. Код файла с генерацией ключей RSA необходимо заменить на:
Python:
import rsa
import pickle
pubkey, privkey = rsa.newkeys(1024)  # генерируем пару ключей
pickle.dump(privkey, open('client_private.key', 'wb+'))  # сохраняем ключ в файл
pickle.dump(pubkey, open('server_publickey', 'wb+'))  # сохраняем ключ в файл
3. Для работы упаковщика файлов при использовании PyArmor необходимо установить PyInstaller с помощью pip.

Хоть и не существует публичных деобфускаторов PyArmor, я все равно не рекомендую писать серьезные проекты на Python. Посмотрите в сторону C++, если нет желания или возможности проводить все важные проверки и операции на сервере.
Полностью согласен с твоим постом, но гайд родился в голове после того как я заметил предыдущую подобную тему и лишь захотелось показать что можно более грамотно подойти к этой задаче. Код, конечно, не претендует на звание лучшего, но это всяко лучше того, что я видел до этого. Имхо, питон не предназначен для написания серьезного клиента, как ты сказал, для таких целей лучше использовать более низкоуровневые япы, а содержание моей темы я больше отношу к стебу. И в дополнение к твоему ответу хочу заметить что данные недостаточно подменить тк мы создаем уникальные пары ключей для расшифровки и твой код для генерации ключей неполный, всего их 4: приватный и публичный для клиента и сервера, соответственно.
Вот это - server_private_key = pickle.load(open('server_private.key', 'rb')) убивает весь смысл шифровки.
Верно заметил, но если более грамотно хранить ключи и немного усложнить алгоритм шифрования/расшифрованмя то смысл не умрет пока pyarmor остается неприступным для тех, кто крякает софты после уроков.
 
всем прив верите ли вы в призраков ???
Забаненный
Статус
Оффлайн
Регистрация
17 Авг 2018
Сообщения
863
Реакции[?]
338
Поинты[?]
0
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Так приватный ключ можно вообще в программе не хранить, зачем ???
 
Участник
Статус
Оффлайн
Регистрация
26 Июн 2020
Сообщения
1,118
Реакции[?]
210
Поинты[?]
8K
это мак адрес как бы, а не хвид
Хвид - это индефикация компьютера, не имеет смысла каким алгоритмом. Хотя использовать его не стоит, банальный сброс сети - изменение его комбинаций.
CzarAlex getnode(), то бишь Mac адрес можно поделать через реестр ?
 
Последнее редактирование:
Начинающий
Статус
Оффлайн
Регистрация
10 Окт 2019
Сообщения
19
Реакции[?]
13
Поинты[?]
0
а нуда,это же пайтон.Защитили... угу
Похоже что после того как ты декомпилировал скрипт на питоне, не одного сообщение от тебя не воспринимается в серьёз
 
Пользователь
Статус
Оффлайн
Регистрация
12 Июн 2019
Сообщения
868
Реакции[?]
127
Поинты[?]
0
Похоже что после того как ты декомпилировал скрипт на питоне, не одного сообщение от тебя не воспринимается в серьёз
Я не понимаю что за бред ты щас сказал.Походу ты вообще не понимаешь что питон язык легко декомириуемый и даже модераторы это доказывали.Твой pyarmor будет сломан легче чем кряк ксяоми.Мне жалко детей которым втерели дичь что теперь питон также защищён как и языки C
 
Пользователь
Статус
Оффлайн
Регистрация
17 Мар 2021
Сообщения
400
Реакции[?]
102
Поинты[?]
0
Я не понимаю что за бред ты щас сказал.Походу ты вообще не понимаешь что питон язык легко декомириуемый и даже модераторы это доказывали.Твой pyarmor будет сломан легче чем кряк ксяоми.Мне жалко детей которым втерели дичь что теперь питон также защищён как и языки C
новые версий питона на которых нет декомпиляторов так не думают
 
Олдфаг
Статус
Оффлайн
Регистрация
18 Фев 2019
Сообщения
2,826
Реакции[?]
1,853
Поинты[?]
24K
новые версий питона на которых нет декомпиляторов так не думают
Не обязательно же декомпилировать все .pyc файлы. И без этого их можно достаточно легко пропатчить.
 
Пользователь
Статус
Оффлайн
Регистрация
12 Июн 2019
Сообщения
868
Реакции[?]
127
Поинты[?]
0
новые версий питона на которых нет декомпиляторов так не думают
а ты думаешь будут декомпилировать одной кнопкой?
Это дело времени чел.Все это можно обойти в томже IDA и даже в Ollydbg и вырезать говяную защиту.
Об"ясняю работу питона1624877336548.png
И на этапе интерпритатора подключаеться С,почему? Потому-что язык зделан на С.Питон високо-уровненвый язык и крякнуть его не так уж и сложно.
Когда твоё ПО кряшнеться питон даст полный отчёт почему,и считай тут будет встроенный дебагер.
Моё мнение что язык сделан для быстрого создания макета и повтора его потом на С.Даже большинство либ сделаны на С для скорости обработки.У языка уже прошло время хайпа
hkon был слит по фактам и обиженый
 
Эксперт
Статус
Оффлайн
Регистрация
9 Апр 2020
Сообщения
1,367
Реакции[?]
644
Поинты[?]
4K
Я не понимаю что за бред ты щас сказал.Походу ты вообще не понимаешь что питон язык легко декомириуемый и даже модераторы это доказывали.Твой pyarmor будет сломан легче чем кряк ксяоми.Мне жалко детей которым втерели дичь что теперь питон также защищён как и языки C
Ты заебал меня конкретно.
Если питон так лего реверснуть, вот тебе
Пожалуйста, авторизуйтесь для просмотра ссылки.
, давай исходники exe, там всего 2 уровня защиты, любое твое "мне что, делать нечего?!" будет воспринято как слив.
И после этого можешь по теме питона вообще свой пиздак не открывать.
 
Сверху Снизу