Open EloiStree opened 6 months ago
Dans ce premier exercice nous créons un interface graphique sur Scratch pour plus tard controller des actions sur notre ordinateur.
Scratch de ce tutorial: https://scratch.mit.edu/projects/1022612664/editor
Ce qui est imporant ici c'est d'utiliser le "wsvar " au début du nom pour facilement la trouver and l'HTML de la page web.
Utiliser Remove Background: https://www.remove.bg Et Krita (ou autre): https://krita.org/fr/ Pour nettoyer l'image. Group après remove background
Seul après recadrage dans Krita.
Si vous avez besoin de cliquer plusieurs fois d'affiler sur le bouton. (Car le code qui suit détecte le changement de valeur seulement.)
Cette tache est un peu longue à faire car il faut tout dupliquer puis donner un numéro à la main à toutes les touches. (76 C'étais bien pour mon image.)
Si vous avez le temps, vous pouvez personnaliser les boutons avec un constume.
Astuce: Vous pouvez double cliquer sur une image en jeu dans l'éditeur pour les customiser
Ici l'exercice n'est pas de comprendre le code que nous allons utiliser mais de le copier coller.
( Double clique sur tamper monkey pour ouvrir le menu )
Source sur GitHub pour avoir la dernier version: https://github.com/EloiStree/2024_05_10_TamperMonkeyToRsaTunnelingIID/blob/main/ScratchToLocalWebsocket/ScratchVarToLocalWebsocket.js
Code au moment de l'écriture de ce tutorial
// ==UserScript==
// @name Push Scratch wsvar to Local WS IID
// @namespace http://tampermonkey.net/
// @version 0.1
// @description Source: https://github.com/EloiStree/2024_05_10_TamperMonkeyToRsaTunnelingIID/blob/main/ScratchToLocalWebsocket/ScratchVarToLocalWebsocket.js
// @description Test zone: https://scratch.mit.edu/projects/1018462085
// @author Eloi stree
// @match https://scratch.mit.edu/projects/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=integergames.be
// @require http://code.jquery.com/jquery-1.8.3.min.js
// @grant none
// ==/UserScript==
//TO LOOK LATER
//https://github.com/travist/jsencrypt
(function() {
'use strict';
/*
What this code do ?
This code overlook at the HTML code when you are on https://scratch.mit.edu/projects/*
It searches about the HTML of a variable display in the scratch game that are a HTML Div code.
The div Id are
- name: .monitor_label_ci1ok
- value: .monitor_value_3Yexa
It add the key value in a dictionary if the value changed only to avoid spam when send outside of the script.
With the help of a unsecure websocket client it send the value as a integer converted to 4 bytes in little format.
To use this script you need to recover it with a websocket server of your own and turn back the 4 bytes to integer.
*/
//Just show in console that the script is injected
console.log("Hello Tamper to Integer :).\n Websocket client will try to connect to websocket server. \n ")
// Creating url to push on local computer at the port 7073 the integer that changed.
var socketUrl= 'ws://localhost:7073';
// Defined the var of the future websocket client
var socket = null;
// Will be use to have a way to know that the server is still in theory connected
var isConnectionValide=false;
// Dictionnary that is storing the previous state when a change happened
// Used to detect any change in the Scratch variable
var previousData = {};
// Do we want to display console log in the browser or not.
var useConsoleDebug=false;
/* This function is use to make some test. It allow to push randomply a integer if the connection is still active */
function PushMessageToServerRandomInteger(){
if(!isConnectionValide){
return;
}
const randomInt = Math.floor(Math.random() * 1000000000) + 1;
PushMessageToServerInteger(randomInt)
}
/*This function send an integer into a exportable value with the date of when it was detected as a ulong format */
function PushMessageToServerIntegerDate(integer){
if(!isConnectionValide){return;}
var value =integer;
// Get the current UTC time in milliseconds
const currentTimeMillis = Date.now();
// Convert to an unsigned long (assuming 64-bit)
const ulongVar = BigInt(currentTimeMillis);
// Create a byte array of length 12
const byteArray = new Uint8Array(12);
// Set the first 4 bytes of the array from the value in little-endian format
byteArray[0] = value & 0xFF;
byteArray[1] = (value >> 8) & 0xFF;
byteArray[2] = (value >> 16) & 0xFF;
byteArray[3] = (value >> 24) & 0xFF;
// Set the next 8 bytes of the array from ulongVar in little-endian format
const view = new DataView(byteArray.buffer);
view.setBigUint64(4, ulongVar, true);
socket.send(byteArray);
if(useConsoleDebug)
console.log("Random date with date:", value)
}
/*This function send an integer into a exportable value and don't attach to it a date value */
function PushMessageToServerInteger(integer){
if(!isConnectionValide){return;}
var value =integer;
const byteArray = new Uint8Array(4);
byteArray[0] = value & 0xFF;
byteArray[1] = (value >> 8) & 0xFF;
byteArray[2] = (value >> 16) & 0xFF;
byteArray[3] = (value >> 24) & 0xFF;
socket.send(byteArray);
if(useConsoleDebug)
console.log("Int Pushed to web local server:", value)
}
var server_is_offline=false;
/*Try to reconnect with a new websocket client if it detect that the current is for any reason not there */
function ReconnectIfOffline(){
if (socket !=null && socket && socket.readyState === WebSocket.OPEN) {
}
else{
isConnectionValide=false
try{
if(useConsoleDebug)
console.log('Try estabalish connection with: '+socketUrl);
socket = new WebSocket(socketUrl);
// Event listener for when the connection is established
socket.addEventListener('open', () => {
console.log('WebSocket connection established');
isConnectionValide=true
});
// Event listener for incoming messages
socket.addEventListener('message', (event) => {
console.log('Received message from server:', event.data);
});
// Event listener for when the connection is closed
socket.addEventListener('close', () => {
console.log('WebSocket connection closed');
isConnectionValide=false
});
// Event listener for errors
socket.addEventListener('error', (error) => {
console.error('WebSocket error:', error);
});
server_is_offline=false;
console.log("Server Online");
}catch(Exception){
server_is_offline=true;
}
}
}
/*This will send key value as integer if it detect the variable start with "wsvar " and connection is open */
function sentKeyValueToOpenWebsocket(label, value) {
if (socket && socket.readyState === WebSocket.OPEN) {
const lowerStr = label.toLowerCase().trim();
if (lowerStr.startsWith("wsvar ")) {
const number = parseInt(value);
//console.log("The string starts with 'wsvar'");
if (!isNaN(number)) {
console.log("Change detectected wsvar int: "+value)
PushMessageToServerInteger(number);
//console.log("The string is a valid integer:", number);
} else {
//console.log("The string is not a valid integer");
}
}
}
}
/*This will look in the HTML code for the Scratch variable as HTML.
If it find the div of the key value that start with "wsvar ". It will set them in the dictionary and notify if it changed*/
function extractAndSendData() {
var dataString = '';
// Find all elements with class 'react-contextmenu-wrapper'
var elements = document.getElementsByClassName('react-contextmenu-wrapper');
// Iterate through each element
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
// Find elements with classes 'monitor_label_ci1ok' and 'monitor_value_3Yexa' within current element
var labelElement = element.querySelector('.monitor_label_ci1ok');
var valueElement = element.querySelector('.monitor_value_3Yexa');
// Extract text content from label and value elements
var label = labelElement ? labelElement.textContent.trim() : '';
var value = valueElement ? valueElement.textContent.trim() : '';
if (label && value) {
if(label.startsWith("wsvar ") ){
dataString += label + ': ' + value + '\n';
if (!previousData[label]) {
previousData[label] = value;
sentKeyValueToOpenWebsocket(label, value);
} else {
if (previousData[label] !== value) {
previousData[label] = value;
console.log("Change detectected: "+value)
sentKeyValueToOpenWebsocket(label, value);
}
}
}
}
}
}
if(useConsoleDebug)
console.log("Interval :) Start ")
setInterval(ReconnectIfOffline, 1000);
setInterval(extractAndSendData,15);
if(useConsoleDebug)
console.log('Code end reach');
})();
Clique droit sur une partie "HTML" du projet.
Il existe sur tout les navigateurs.
Opera GX:
Brave
Chrome
Vous devriez avoir un message comme celui-ci Le client veut se connecter à un websocket local mais n'y arrive pas car il n'existe pas.
Pour la suite de l'aventure nous avons besoin d'installer Python et de créé un server local.
(Version Window)
Télécharger l'installeur : https://www.python.org/downloads/
Valider c'est deux casses ensuite fait next next next.
Par une recherche
par un Window + R suivit d'un appel cmd
print("Hello World")
Voici votre première ligne de commande python sous console. Nous n'allons pas faire du python en console ^^. On va le faire dans un éditeur de code
La où vous avez l'habitue. (Attention pas de nom utilisateur avec é, à ou de espace. Règle d'or en information "AlphaNumérique_09" seulement. La raison est que un cartère spécial peu ne pas être reconnu dans certain langage et créé des bugs. Et un espace peu poser problème dans des lignes de commandes n'utilisant pas " " )
Astuce F5 pour execute sans le menu
# Ceci est un commentaire en Python
# // Celui-ci en JavaScript et en C#
"""
Ceci est un commentaire sur plusieurs lignes en Python
/* Celui-ci en JavaScript et en C#
*/
"""
print("Hello World")
je_suis_une_variable = 0
print(je_suis_une_variable)
# En Python les variables sont dynamiques
# Elles peuvent donc changer de type de contenu
je_suis_une_variable = "Bonjour"
print(je_suis_une_variable)
variable_avec_du_texte = "J'aime les frites"
variable_avec_un_nombre = 3
# Vous pouvez ajouter du texte avec d'autres types de contenu.
# Mais il faut d'abord le transformer en texte
print("> " + variable_avec_du_texte + ": " + str(variable_avec_un_nombre))
# Python offre un outil pour ne pas devoir faire ça
print(f"> {variable_avec_du_texte}: {variable_avec_un_nombre}")
# print() et str() c'est ce que l'on appelle une méthode
# un bout de code d'un autre développeur qui fait une chose pour nous.
# Vous pouvez en créer vous aussi en les "définissant"
def dire_bonjour():
print("Bonjour")
# La définition doit toujours être avant son "appel"
# Vous pouvez l'appeler comme ceci
dire_bonjour()
# On aimerait dire bonjour à une personne
def dire_bonjour_a(nom_de_la_personne):
print(f"Bonjour, {nom_de_la_personne}")
dire_bonjour_a("Eloi")
# On aimerait qu'elle réponde "j'aime les frites" 30 fois
def j_aime_les_frites(nombre_de_print):
for index in range(nombre_de_print):
print(f"J'aime les frites ({index})")
j_aime_les_frites(5)
# S'il aime d'autres choses ?
tableau_de_gouts = ["à la sauce Liégeoise", "aux samouraïs", "dans une mitraillette", "avec un œuf"]
# On aimerait qu'elle réponde "j'aime les frites" avec le tableau
def j_aime_les_frites_avec_un_tableau(tableau_de_gouts):
for valeur_du_tableau in tableau_de_gouts:
print(f"J'aime les frites {valeur_du_tableau}")
j_aime_les_frites_avec_un_tableau(tableau_de_gouts)
# Mais a-t-il faim ?
boolean_a_t_il_faim = False
def as_tu_faim(boolean_a_t_il_faim):
if boolean_a_t_il_faim:
print("Oui, j'ai faim.")
else:
print("Non, mais je mangerais bien une frite pour le fun")
as_tu_faim(boolean_a_t_il_faim)
# Comme Python est un langage interprété, on peut
# importer du code au milieu du script
# Mais c'est déconseillé, on le met généralement en première ligne.
# Importation du temps pour attendre qu'Eloi ait faim
import time
# La fonction time.sleep() permet de geler le temps et d'attendre avant d'exécuter la suite du code
time.sleep(1)
print("Et maintenant tu as faim ?")
as_tu_faim(boolean_a_t_il_faim)
time.sleep(1)
print("Toujours pas faim ?")
as_tu_faim(boolean_a_t_il_faim)
time.sleep(1)
print("Ok, dis-moi quand tu as faim")
as_tu_faim(boolean_a_t_il_faim)
time.sleep(1)
# On peut attendre qu'Eloi commence à vouloir manger
import random
while boolean_a_t_il_faim == False:
as_tu_faim(boolean_a_t_il_faim)
# On attend aléatoirement qu'Eloi ait faim.
boolean_a_t_il_faim = random.randint(0, 10) == 0
# Enfin... C'était pas trop tôt
as_tu_faim(boolean_a_t_il_faim)
Pour pouvoir recevoir les informations de votre navigateur, sur votre ordinateur vous aurez besion d'un server local. Une petite application qui tourne pour écouter et retransmettre (ou faire).
Window + R > CMD
pip3 install websockets
pip3 install asyncio
websocket_server_port=7073
udp_server_port = 7072
# List of IP:PORT to broadcast the data to the apps
broadcast_list_udp_target={"127.0.0.1:404"}
broadcast_list_udp_target={"127.0.0.1:405"}
# Set to True if you want to print the received data of clients
debug_received_data = False
def handle_integer_received(integer):
i=int(integer)
# If you want it out of the script
YourCodeHere.handle_integer_received(integer)
# if you want to broadcast the data to apps with UDP
broadcast_to_targets(int(i))
## If you want in the script
print(f"R|{integer}")
################### Websocket don't touch #####################
import asyncio
import websockets
import struct
import os
import socket
# pip3 install websockets
# pip3 install asyncio
# pip3 install struct
# pip3 install socket
filename = "YourCodeHere.py"
if not os.path.exists(filename):
with open(filename, "w") as f:
# You can add initial content to the file if you want
f.write("""# YourCodeHere.py
def handle_integer_received(integer):
i=int(integer)""")
print(f"File '{filename}' created successfully!")
import YourCodeHere
def broadcast_to_targets(message):
for target in broadcast_list_udp_target:
temp = target.split(":")
target_address = ("127.0.0.1", "")
if len(temp) == 2:
target_address = (temp[0], int(temp[1]))
elif len(temp) == 1:
target_address = ("", int(temp[0]))
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udp_socket.sendto(struct.pack('<i', message), target_address)
udp_socket.close()
def get_current_ip():
hostname = socket.gethostname()
ip_address = socket.gethostbyname(hostname)
return ip_address
async def handle_message(websocket, path):
try:
async for message in websocket:
message_length = len(message)
if message_length == 4:
value1 = struct.unpack('<i', message)[0]
if debug_received_data:
print(f"Received value: {value1} (format: <i)")
handle_integer_received(int(value1))
elif message_length == 12:
value1, value2 = struct.unpack('<iQ', message)
if debug_received_data:
print(f"Received values: {value1}, {value2} (format: <iQ)")
handle_integer_received(int(value1))
elif message_length == 16:
value1, value2, value3 = struct.unpack('<iiQ', message)
if debug_received_data:
print(f"Received values: {value1}, {value2}, {value3} (format: <iiQ)")
handle_integer_received(int(value1))
except websockets.ConnectionClosedError as e:
print(f"Connection closed with error: {e}")
# Wait a bit before trying to reconnect
await asyncio.sleep(5)
start_server = websockets.serve(handle_message, "", websocket_server_port)
asyncio.get_event_loop().run_until_complete(start_server)
print("Current IP:", get_current_ip())
print("WebSocket server is listening on port 7073")
################### UDP don't touch #####################
def integer_listener_client_udp(host, port):
# Create a UDP socket
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Bind the socket to the host and port
udp_socket.bind((host, port))
print("UDP integer listener client is now listening on {}:{}".format(host, port))
try:
while True:
# Receive data from the socket
data, address = udp_socket.recvfrom(64)
if len(data)==4:
received_integer = struct.unpack('<i', data)[0]
handle_integer_received(received_integer)
elif len(data)==12:
received_integer = struct.unpack('<iQ', data)[0]
handle_integer_received(received_integer)
elif len(data)==16:
received_integer = struct.unpack('<iiQ', data)[0]
handle_integer_received(received_integer)
else: continue
#print("Received integer:", received_integer, "from", address)
except KeyboardInterrupt:
print("UDP integer listener client stopped.")
finally:
# Close the socket
udp_socket.close()
asyncio.get_event_loop().run_in_executor(None, integer_listener_client_udp, "", udp_server_port)
asyncio.get_event_loop().run_forever()
Pousser sur azer et les touches de l'écran:
https://scratch.mit.edu/projects/1022612664/editor/
Profiter de votre magnifique premiers server WebSocket en python !
Replace BGB by Wow or other.
Vous avez plusieurs choix:
YourCodehere.py
def handle_integer_received(integer):
i=int(integer)
# If you want it out of the script
YourCodeHere.handle_integer_received(integer)
# if you want to broadcast the data to apps with UDP
broadcast_to_targets(int(i))
## If you want in the script
Dans le code donné plus tôt vous avez un YourCodeHere.handle_integer_received(integer)
Celui-ci invoke une action dans le fichier YourCodehere.py
à côté
Voir Exercice précèdent
Last version: https://github.com/EloiStree/2024_05_17_BasicPythonUdpWebsocketIID/blob/main/SendUdpInteger/ReceivedUdpInteger.py
def handle_integer_received(integer):
value=int(integer)
print(value)
import socket
import struct
def integer_listener_client_udp(host, port):
# Create a UDP socket
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Bind the socket to the host and port
udp_socket.bind((host, port))
print("UDP integer listener client is now listening on {}:{}".format(host, port))
try:
while True:
# Receive data from the socket
data, address = udp_socket.recvfrom(64)
if len(data)==4:
received_integer = struct.unpack('<i', data)[0]
handle_integer_received(received_integer)
elif len(data)==12:
received_integer = struct.unpack('<iQ', data)[0]
handle_integer_received(received_integer)
elif len(data)==16:
received_integer = struct.unpack('<iiQ', data)[0]
handle_integer_received(received_integer)
else: continue
#print("Received integer:", received_integer, "from", address)
except KeyboardInterrupt:
print("UDP integer listener client stopped.")
finally:
# Close the socket
udp_socket.close()
# Example usage:
if __name__ == "__main__":
HOST = "0.0.0.0" # Listen on all available interfaces
PORT = 404 # Example port (change to your desired port)
integer_listener_client_udp(HOST, PORT)
Si vous êtes pressé et non axés sécurité, vous pouvez désactiver les pare feu.
Si vous voulez n'ouvrir que le port cible. https://youtu.be/NUaCl5Yqz3g?t=27
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
R
Note
import pyautogui
import time
time.sleep(5)
# Commentaire sur une ligne
"""
Commentaire sur plusieur
ligne
"""
print("Pousse sur R pour recommencer")
pyautogui.keyDown('r')
pyautogui.keyUp('r')
time.sleep(0.1)
print("Sword")
pyautogui.keyDown('x')
pyautogui.keyUp('x')
time.sleep(0.1)
print("kunai")
pyautogui.keyDown('z')
pyautogui.keyUp('z')
time.sleep(0.1)
print("Aller à gauche")
pyautogui.keyDown('left')
pyautogui.keyUp('left')
time.sleep(0.1)
print("Sauter")
pyautogui.keyDown('up')
pyautogui.keyUp('up')
time.sleep(0.1)
print("Aller à droite")
pyautogui.keyDown('right')
pyautogui.keyUp('right')
print("Doubel saut")
pyautogui.keyDown('up')
pyautogui.keyUp('up')
time.sleep(0.1)
pyautogui.keyDown('up')
pyautogui.keyUp('up')
https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes VK_CODES = { 'LBUTTON': 0x01, # Left mouse button 'RBUTTON': 0x02, # Right mouse button 'CANCEL': 0x03, # Control-break processing 'MBUTTON': 0x04, # Middle mouse button (three-button mouse) 'XBUTTON1': 0x05, # X1 mouse button 'XBUTTON2': 0x06, # X2 mouse button 'BACK': 0x08, # BACKSPACE key 'TAB': 0x09, # TAB key 'CLEAR': 0x0C, # CLEAR key 'RETURN': 0x0D, # ENTER key 'SHIFT': 0x10, # SHIFT key 'CONTROL': 0x11, # CTRL key 'MENU': 0x12, # ALT key 'PAUSE': 0x13, # PAUSE key 'CAPITAL': 0x14, # CAPS LOCK key 'KANA': 0x15, # IME Kana mode 'HANGUEL': 0x15, # IME Hanguel mode (maintained for compatibility; use HANGUL) 'HANGUL': 0x15, # IME Hangul mode 'JUNJA': 0x17, # IME Junja mode 'FINAL': 0x18, # IME final mode 'HANJA': 0x19, # IME Hanja mode 'KANJI': 0x19, # IME Kanji mode 'ESCAPE': 0x1B, # ESC key 'CONVERT': 0x1C, # IME convert 'NONCONVERT': 0x1D, # IME nonconvert 'ACCEPT': 0x1E, # IME accept 'MODECHANGE': 0x1F, # IME mode change request 'SPACE': 0x20, # SPACEBAR 'PRIOR': 0x21, # PAGE UP key 'NEXT': 0x22, # PAGE DOWN key 'END': 0x23, # END key 'HOME': 0x24, # HOME key 'LEFT': 0x25, # LEFT ARROW key 'UP': 0x26, # UP ARROW key 'RIGHT': 0x27, # RIGHT ARROW key 'DOWN': 0x28, # DOWN ARROW key 'SELECT': 0x29, # SELECT key 'PRINT': 0x2A, # PRINT key 'EXECUTE': 0x2B, # EXECUTE key 'SNAPSHOT': 0x2C, # PRINT SCREEN key 'INSERT': 0x2D, # INS key 'DELETE': 0x2E, # DEL key 'HELP': 0x2F, # HELP key '0': 0x30, # 0 key '1': 0x31, # 1 key '2': 0x32, # 2 key '3': 0x33, # 3 key '4': 0x34, # 4 key '5': 0x35, # 5 key '6': 0x36, # 6 key '7': 0x37, # 7 key '8': 0x38, # 8 key '9': 0x39, # 9 key 'A': 0x41, # A key 'B': 0x42, # B key 'C': 0x43, # C key 'D': 0x44, # D key 'E': 0x45, # E key 'F': 0x46, # F key 'G': 0x47, # G key 'H': 0x48, # H key 'I': 0x49, # I key 'J': 0x4A, # J key 'K': 0x4B, # K key 'L': 0x4C, # L key 'M': 0x4D, # M key 'N': 0x4E, # N key 'O': 0x4F, # O key 'P': 0x50, # P key 'Q': 0x51, # Q key 'R': 0x52, # R key 'S': 0x53, # S key 'T': 0x54, # T key 'U': 0x55, # U key 'V': 0x56, # V key 'W': 0x57, # W key 'X': 0x58, # X key 'Y': 0x59, # Y key 'Z': 0x5A, # Z key 'LWIN': 0x5B, # Left Windows key (Natural keyboard) 'RWIN': 0x5C, # Right Windows key (Natural keyboard) 'APPS': 0x5D, # Applications key (Natural keyboard) 'SLEEP': 0x5F, # Computer Sleep key 'NUMPAD0': 0x60, # Numeric keypad 0 key 'NUMPAD1': 0x61, # Numeric keypad 1 key 'NUMPAD2': 0x62, # Numeric keypad 2 key 'NUMPAD3': 0x63, # Numeric keypad 3 key 'NUMPAD4': 0x64, # Numeric keypad 4 key 'NUMPAD5': 0x65, # Numeric keypad 5 key 'NUMPAD6': 0x66, # Numeric keypad 6 key 'NUMPAD7': 0x67, # Numeric keypad 7 key 'NUMPAD8': 0x68, # Numeric keypad 8 key 'NUMPAD9': 0x69, # Numeric keypad 9 key 'MULTIPLY': 0x6A, # Multiply key 'ADD': 0x6B, # Add key 'SEPARATOR': 0x6C, # Separator key 'SUBTRACT': 0x6D, # Subtract key 'DECIMAL': 0x6E, # Decimal key 'DIVIDE': 0x6F, # Divide key 'F1': 0x70, # F1 key 'F2': 0x71, # F2 key 'F3': 0x72, # F3 key 'F4': 0x73, # F4 key 'F5': 0x74, # F5 key 'F6': 0x75, # F6 key 'F7': 0x76, # F7 key 'F8': 0x77, # F8 key 'F9': 0x78, # F9 key 'F10': 0x79, # F10 key 'F11': 0x7A, # F11 key 'F12': 0x7B, # F12 key 'F13': 0x7C, # F13 key 'F14': 0x7D, # F14 key 'F15': 0x7E, # F15 key 'F16': 0x7F, # F16 key 'F17': 0x80, # F17 key 'F18': 0x81, # F18 key 'F19': 0x82, # F19 key 'F20': 0x83, # F20 key 'F21': 0x84, # F21 key 'F22': 0x85, # F22 key 'F23': 0x86, # F23 key 'F24': 0x87, # F24 key 'NUMLOCK': 0x90, # NUM LOCK key 'SCROLL': 0x91, # SCROLL LOCK key '
import asyncio
import websockets
import json
from obswebsocket import obsws, requests
# OBS WebSocket connection details
OBS_HOST = 'localhost'
OBS_PORT = 4444
OBS_PASSWORD = 'your_password'
# WebSocket server details
WEBSOCKET_HOST = 'localhost'
WEBSOCKET_PORT = 8765
# Initialize OBS WebSocket client
obs_client = obsws(OBS_HOST, OBS_PORT, OBS_PASSWORD)
async def start_obs_recording():
try:
obs_client.call(requests.StartRecording())
print("Recording started.")
except Exception as e:
print(f"Failed to start recording: {e}")
async def stop_obs_recording():
try:
obs_client.call(requests.StopRecording())
print("Recording stopped.")
except Exception as e:
print(f"Failed to stop recording: {e}")
async def handler(websocket, path):
async for message in websocket:
data = json.loads(message)
action = data.get('action')
if action == 'start_recording':
await start_obs_recording()
elif action == 'stop_recording':
await stop_obs_recording()
else:
print(f"Unknown action: {action}")
async def main():
# Connect to OBS
obs_client.connect()
# Start the WebSocket server
async with websockets.serve(handler, WEBSOCKET_HOST, WEBSOCKET_PORT):
print(f"WebSocket server started on ws://{WEBSOCKET_HOST}:{WEBSOCKET_PORT}")
await asyncio.Future() # Run forever
try:
asyncio.run(main())
except KeyboardInterrupt:
pass
finally:
obs_client.disconnect()
print("OBS WebSocket client disconnected.")
Key Logger in C# to use in the project.
https://github.com/EloiStree/2024_02_21_OpenSourceKeyLoggerForUnity3D/releases/tag/V0
using System;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.Json;
namespace KeyboardInputConsoleApp
{
class Program
{
static int Port = 7072;
static IPAddress BroadcastAddress = IPAddress.Parse("127.0.0.1");
[DllImport("user32.dll")]
public static extern short GetAsyncKeyState(int vKey);
static bool[] previousKeyState = new bool[256];
public class JsonConfig
{
public int m_offset { get; set; } = 160000;
public int m_offset_press { get; set; } = 1000;
public int m_offset_release { get; set; } = 2000;
public int m_port { get; set; } = 7072;
public string m_ip_target { get; set; } = "127.0.0.1";
}
static void Main(string[] args)
{
string filePath = "Config.json";
JsonConfig config= new JsonConfig();
if (!File.Exists(filePath))
{
// Read the JSON content from the file
string outputJsonString = JsonSerializer.Serialize(config, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText(filePath, outputJsonString);
}
if (File.Exists(filePath))
{
// Read the JSON content from the file
string jsonString = File.ReadAllText(filePath);
config = JsonSerializer.Deserialize<JsonConfig>(jsonString);
Console.WriteLine(jsonString);
}
Port = config.m_port;
BroadcastAddress = IPAddress.Parse(config.m_ip_target);
int offset = config.m_offset;
Console.WriteLine("Offset: " + offset);
// Create UDP client
UdpClient udpClient = new UdpClient();
while (true)
{
for (int i = 0; i < 256; i++)
{
bool isKeyPressed = (GetAsyncKeyState(i) & 0x8000) != 0;
if (isKeyPressed != previousKeyState[i])
{
int temp = isKeyPressed ? offset + config.m_offset_press + i : offset + config.m_offset_release + i;
string message = $"Key Pressed: {temp}" ;
Console.WriteLine(message);
SendUdpMessage(udpClient, temp);
previousKeyState[i] = isKeyPressed;
}
}
Thread.Sleep(TimeSpan.FromMicroseconds(10));
}
}
static void SendUdpMessage(UdpClient client, int intValue)
{
byte[] bytes1 = BitConverter.GetBytes(intValue);
client.Send(bytes1, bytes1.Length, new IPEndPoint(BroadcastAddress, Port));
}
}
}
import pyautogui
# Press the 'A' key
pyautogui.keyDown('a')
# Release the 'A' key
pyautogui.keyUp('a')
from pynput.keyboard import Key, Controller
# Create a keyboard controller object
keyboard = Controller()
# Simulate pressing and releasing the 'A' key
keyboard.press('a')
keyboard.release('a')
``` py
import ctypes
from ctypes import wintypes
import time
import win32gui
user32 = ctypes.WinDLL('user32', use_last_error=True)
# Define constants
WM_KEYDOWN = 0x0100
WM_KEYUP = 0x0101
VK_A = 0x41
# Find the handle to the target window (e.g., Notepad)
hwnd = win32gui.FindWindow(None, "Untitled - Notepad") # Change this to your target window title
if hwnd == 0:
print("Target window not found!")
else:
# Press the 'A' key
user32.PostMessageW(hwnd, WM_KEYDOWN, VK_A, 0)
# Small delay to simulate a key press duration
time.sleep(0.1)
# Release the 'A' key
user32.PostMessageW(hwnd, WM_KEYUP, VK_A, 0)
print("Key 'A' pressed and released.")
import ctypes
import time
# Constants
KEYEVENTF_KEYDOWN = 0x0000
KEYEVENTF_KEYUP = 0x0002
VK_A = 0x41 # Virtual-key code for the 'A' key
# Load the user32.dll
user32 = ctypes.windll.user32
def press_key(hexKeyCode):
user32.keybd_event(hexKeyCode, 0, KEYEVENTF_KEYDOWN, 0)
def release_key(hexKeyCode):
user32.keybd_event(hexKeyCode, 0, KEYEVENTF_KEYUP, 0)
if __name__ == "__main__":
time.sleep(2) # Sleep for 2 seconds to give you time to switch to the target window
press_key(VK_A)
time.sleep(0.1) # Hold the key for a short duration
release_key(VK_A)
Envoyé un text en UDP
import socket
def send_udp_message(target_ip, target_port, message):
# Create a UDP socket
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
# Send the message
udp_socket.sendto(message.encode(), (target_ip, target_port))
print(f"Message sent to {target_ip}:{target_port}")
except Exception as e:
print(f"Error sending message: {e}")
finally:
# Close the socket
udp_socket.close()
# Define target IP, port, and message
target_ip = "192.168.1.100" # Replace with the target IP address
target_port = 404 # Target port
message = "Hello, this is a test message!" # Message to send
# Send the UDP message
send_udp_message(target_ip, target_port, message)
Recevoir le texte UDP
import socket
def udp_server(host='0.0.0.0', port=404):
# Create a UDP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Bind the socket to the address and port
server_address = (host, port)
print(f'Starting UDP server on {server_address[0]} port {server_address[1]}')
sock.bind(server_address)
while True:
print('Waiting to receive message...')
data, address = sock.recvfrom(4096)
print(f'Received {len(data)} bytes from {address}')
print(data.decode('utf-8'))
# If needed, send a response back to the client
# sent = sock.sendto(data, address)
# print(f'Sent {sent} bytes back to {address}')
if __name__ == "__main__":
udp_server()
import pyxinput
import time
import socket
import struct
import random
#pyxinput.test_virtual()
# AxisLx , Left Stick X-Axis
# AxisLy , Left Stick Y-Axis
# AxisRx , Right Stick X-Axis
# AxisRy , Right Stick Y-Axis
# BtnBack , Menu/Back Button
# BtnStart , Start Button
# BtnA , A Button
# BtnB , B Button
# BtnX , X Button
# BtnY , Y Button
# BtnThumbL , Left Thumbstick Click
# BtnThumbR , Right Thumbstick Click
# BtnShoulderL , Left Shoulder Button
# BtnShoulderR , Right Shoulder Button
# Dpad , Set Dpad Value (0 = Off, Use DPAD_### Constants) 1 up 2 down 3 left 4 right
# TriggerL , Left Trigger
# TriggerR , Right Trigger
listener_udp_address = ('', 7000)
int_offset=450000
int_player_offset=100
max_input=3
pv={}
pr={}
def set_value_for_all(value_key,value):
for key in pv:
pv[key].set_value(value_key, value)
for i in range(1,max_input+1):
pv[str(i)] = pyxinput.vController()
pr[str(i)] = pyxinput.rController(i)
def release_all():
set_value_for_all('BtnA', 0),
set_value_for_all('BtnB', 0),
set_value_for_all('BtnX', 0),
set_value_for_all('BtnY', 0),
set_value_for_all('Dpad', 0),
set_value_for_all('BtnThumbL', 0),
set_value_for_all('BtnThumbR', 0),
set_value_for_all('BtnShoulderL', 0),
set_value_for_all('BtnShoulderR', 0),
set_value_for_all('BtnStart', 0),
set_value_for_all('BtnBack', 0),
set_value_for_all('TriggerL', 0),
set_value_for_all('TriggerR', 0),
set_value_for_all('AxisLx', 0),
set_value_for_all('AxisLy', 0),
set_value_for_all('AxisRx', 0),
set_value_for_all('AxisRy', 0),
def get_random_11():
return random.uniform(-1.0, 1.0)
def all_player_move_randomly():
for key in pv:
pv[key].set_value('AxisLx', get_random_11())
pv[key].set_value('AxisLy', get_random_11())
pv[key].set_value('AxisRx', get_random_11())
pv[key].set_value('AxisRy', get_random_11())
button_dico_all = {
#ABXY
0: lambda: release_all(),
1: lambda: all_player_move_randomly(),
1001: lambda: set_value_for_all('BtnA', 1),
2001: lambda: set_value_for_all('BtnA', 0),
1002: lambda: set_value_for_all('BtnB', 1),
2002: lambda: set_value_for_all('BtnB', 0),
1003: lambda: set_value_for_all('BtnX', 1),
2003: lambda: set_value_for_all('BtnX', 0),
1004: lambda: set_value_for_all('BtnY', 1),
2004: lambda: set_value_for_all('BtnY', 0),
#DPAD
1005: lambda: set_value_for_all('Dpad', 2),# 2 down
2005: lambda: set_value_for_all('Dpad', 0),
1006: lambda: set_value_for_all('Dpad', 1),# 1 up
2006: lambda: set_value_for_all('Dpad', 0),
1007: lambda: set_value_for_all('Dpad', 4),# 4 left
2007: lambda: set_value_for_all('Dpad', 0),
1008: lambda: set_value_for_all('Dpad', 8),# 8 right
2008: lambda: set_value_for_all('Dpad', 0),
#THUMB
1009: lambda: set_value_for_all('BtnThumbL', 1),
2009: lambda: set_value_for_all('BtnThumbL', 0),
1010: lambda: set_value_for_all('BtnThumbR', 1),
2010: lambda: set_value_for_all('BtnThumbR', 0),
#SHOULDER
1011: lambda: set_value_for_all('BtnShoulderL', 1),
2011: lambda: set_value_for_all('BtnShoulderL', 0),
1012: lambda: set_value_for_all('BtnShoulderR', 1),
2012: lambda: set_value_for_all('BtnShoulderR', 0),
#START BACK
1013: lambda: set_value_for_all('BtnStart', 1),
2013: lambda: set_value_for_all('BtnStart', 0),
1014: lambda: set_value_for_all('BtnBack', 1),
2014: lambda: set_value_for_all('BtnBack', 0),
#TRIGGER
2020: lambda: set_value_for_all('TriggerL', 0),
2021: lambda: set_value_for_all('TriggerL', 0.1),
2022: lambda: set_value_for_all('TriggerL', 0.2),
2023: lambda: set_value_for_all('TriggerL', 0.3),
2024: lambda: set_value_for_all('TriggerL', 0.4),
2025: lambda: set_value_for_all('TriggerL', 0.5),
2026: lambda: set_value_for_all('TriggerL', 0.6),
2027: lambda: set_value_for_all('TriggerL', 0.7),
2028: lambda: set_value_for_all('TriggerL', 0.8),
2029: lambda: set_value_for_all('TriggerL', 0.9),
2030: lambda: set_value_for_all('TriggerL', 1),
#TRIGGER
2040: lambda: set_value_for_all('TriggerR', 0),
2041: lambda: set_value_for_all('TriggerR', 0.1),
2042: lambda: set_value_for_all('TriggerR', 0.2),
2043: lambda: set_value_for_all('TriggerR', 0.3),
2044: lambda: set_value_for_all('TriggerR', 0.4),
2045: lambda: set_value_for_all('TriggerR', 0.5),
2046: lambda: set_value_for_all('TriggerR', 0.6),
2047: lambda: set_value_for_all('TriggerR', 0.7),
2048: lambda: set_value_for_all('TriggerR', 0.8),
2049: lambda: set_value_for_all('TriggerR', 0.9),
2050: lambda: set_value_for_all('TriggerR', 1),
3100: lambda: set_value_for_all('AxisLx', -1),
3101: lambda: set_value_for_all('AxisLx', -0.90),
3102: lambda: set_value_for_all('AxisLx', -0.75),
3103: lambda: set_value_for_all('AxisLx', -0.5),
3104: lambda: set_value_for_all('AxisLx', -0.25),
3105: lambda: set_value_for_all('AxisLx', 0),
3106: lambda: set_value_for_all('AxisLx', 0.25),
3107: lambda: set_value_for_all('AxisLx', 0.5),
3108: lambda: set_value_for_all('AxisLx', 0.75),
3109: lambda: set_value_for_all('AxisLx', 0.90),
3110: lambda: set_value_for_all('AxisLx', 1),
3111: lambda: set_value_for_all('AxisLy', get_random_11()),
3200: lambda: set_value_for_all('AxisLy', -1),
3201: lambda: set_value_for_all('AxisLy', -0.90),
3202: lambda: set_value_for_all('AxisLy', -0.75),
3203: lambda: set_value_for_all('AxisLy', -0.5),
3204: lambda: set_value_for_all('AxisLy', -0.25),
3205: lambda: set_value_for_all('AxisLy', 0),
3206: lambda: set_value_for_all('AxisLy', 0.25),
3207: lambda: set_value_for_all('AxisLy', 0.5),
3208: lambda: set_value_for_all('AxisLy', 0.75),
3209: lambda: set_value_for_all('AxisLy', 0.90),
3210: lambda: set_value_for_all('AxisLy', 1),
3211: lambda: set_value_for_all('AxisLy', get_random_11()),
3300: lambda: set_value_for_all('AxisRx', -1),
3301: lambda: set_value_for_all('AxisRx', -0.90),
3302: lambda: set_value_for_all('AxisRx', -0.75),
3303: lambda: set_value_for_all('AxisRx', -0.5),
3304: lambda: set_value_for_all('AxisRx', -0.25),
3305: lambda: set_value_for_all('AxisRx', 0),
3306: lambda: set_value_for_all('AxisRx', 0.25),
3307: lambda: set_value_for_all('AxisRx', 0.5),
3308: lambda: set_value_for_all('AxisRx', 0.75),
3309: lambda: set_value_for_all('AxisRx', 0.90),
3310: lambda: set_value_for_all('AxisRx', 1),
3311: lambda: set_value_for_all('AxisLy', get_random_11()),
3400: lambda: set_value_for_all('AxisRy', -1),
3401: lambda: set_value_for_all('AxisRy', -0.90),
3402: lambda: set_value_for_all('AxisRy', -0.75),
3403: lambda: set_value_for_all('AxisRy', -0.5),
3404: lambda: set_value_for_all('AxisRy', -0.25),
3405: lambda: set_value_for_all('AxisRy', 0),
3406: lambda: set_value_for_all('AxisRy', 0.25),
3407: lambda: set_value_for_all('AxisRy', 0.5),
3408: lambda: set_value_for_all('AxisRy', 0.75),
3409: lambda: set_value_for_all('AxisRy', 0.90),
3410: lambda: set_value_for_all('AxisRy', 1),
3411: lambda: set_value_for_all('AxisLy', get_random_11()),
}
# Create a UDP socket
# Bind the socket to a specific IP address and port
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(listener_udp_address)
def integer_to_xbox_input(int_value):
if button_dico_all.get(int_value) is not None:
print(f"Received {int_value}")
button_dico_all[int_value]()
else :
print(f"Received {int_value} not found")
print(f"Listening for incoming data... port {listener_udp_address[1]}")
# Listen for incoming data
while True:
byte_received, address = sock.recvfrom(1024) # Adjust the buffer size as needed
print(f'Received {len(byte_received)} bytes from {address}: {byte_received}')
if byte_received is not None:
if len(byte_received) == 16:
index = struct.unpack('<i', byte_received[0:4])[0]
value = struct.unpack('<i', byte_received[4:8])[0]
ulong_milliseconds = struct.unpack('<q', byte_received[8:16])[0]
print(f"Received Bytes {index} | {value} | { ulong_milliseconds}")
integer_to_xbox_input(value)
import socket
# Get the IP address of the current machine
ip_address = socket.gethostbyname(socket.gethostname())
# Print the IP address
print(f'My IP address is: {ip_address}')
# Create a UDP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Bind the socket to a specific address and port
server_address = ('', 404)
sock.bind(server_address)
print('Listening for UDP messages on port 404...')
while True:
# Receive a message and the client address
data, address = sock.recvfrom(4096)
# Print the received message
print(f'Received message: {data.decode()} from {address[0]}:{address[1]}')
import socket
import time
def send_udp_packet(ip, port):
# Create a UDP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Send a UDP packet to the specified IP address and port
sock.sendto(b"Hello, UDP!", (ip, port))
# Close the socket
sock.close()
# Specify the IP address and port to send the UDP packet to
ip = "127.0.0.1" # Replace with the desired IP address
ip = "192.168.150.3" # Replace with the desired IP address
port = 404 # Replace with the desired port number
# Call the function to send the UDP packet
while True:
time.sleep(1)
send_udp_packet(ip, port)
Bienvenue dans ce guide
Bienvenue à vous dans ce guide sur comment contrôler des jeux en local sur Windows et des ordinateurs à distance à l'aide d'un entier entre -2147483648 et 2147483647.
Le but de l'atelier est de pratiquer Python et Scratch, car tous deux vous permettent d'apprendre à programmer et de créer des macros (succession d'actions dans le temps).
Si vous maîtrisez cet exercice, vous gagnerez le pouvoir de contrôler à distance toutes les actions possibles sur des ordinateurs distants via Python :).
Liste non exhaustive :
Python est extrêmement versatile et alimenté par la communauté.
Bon apprentissage à vous.
L'utilité d'utiliser un entier avec 4 milliards de possibilités ?
Je peux vous trouver d'autres raisons issues de mon passé qui m'amènent à utiliser des entiers comme commande d'action à distance.
Exemple : contrôler un drone en utilisant ces deux joysticks
190009876
Avec un peu plus de précisions si nécessaire :
2099887766
Exercice 1
Dans cet atelier, nous allons apprendre via un Drum Pad en Scratch sur votre ordinateur.
Exercice 2
Via une table d'indexation et de l'UDP, vous allez contrôler un champion dans World of Warcraft.
Le but de l'exercice est en groupe d'aller tuer Lardeur :
Scratch demo: