Category: Programmation

Why the eSport is a security fail ?

Today I will talk about one of my favourite domain, the electronic sport competitions and the underground activities behind.

I will try to explain why the eSport is a security fail, I’m a old counter-strike player (CS:GO actually) so I will take this sample.

I watched many professionnals players, I followed the eSport scene many years and when I watched movies or streams directly, I was like “wow they are really strong”.

But something was wrong, some players was god like, I don’t considere myself like bad at counter-strike, I did some lan tournaments, I was global elite on the game (highest level actually) etc…

So I started to introduce myself under another nickname on a cheat community (unknowncheats forums).

I started to create some cheats on a really well know game (I will not share the name here because they decided to arrest some cheats developers recently), not to share or sell them, only for my own knowledge to learn new things about the reverse engineering (my weakness in the computer security).

And the game surprised me, there is no anticheat, only some anti-debuggers on the last version of the game (IsDebuggerPresent and some first-time exceptions that you can disable with xdbg).

To inject in the game process, you can use a simple LoadLibrary method, some guys use a manual mapping method but injections methods are mostly not considered.

Like you probably know, there is two type of cheats, internals (dll injection) and externals (actions on the game process without injections).

This game surprised me again when I tried a simple WriteProcessMemory on the online mode, you can enable the god mode, run faster, jump or fly like superman and you will be never detected because the game work in p2p mode and trust everything from the client, you can kick or crash the others players remotely.

There is also some kernel methods for the paranoid cheaters, you can use a vulnerable driver to be ring0 and avoid some anticheats:

https://github.com/Zer0Mem0ry/KernelBhop

After few months, I finally created a fully functionnal cheat for this game with ImGui included etc… I was able to execute all the game internal functions with some hashes (the game use a sort of custom virtual table where all game functions was registered with a hash, so the solution between the updates was to create an array with the old hashes and the new hashes, call the old hash, use a custom translator to call the new hash from the old one).

Now I will talk about CS:GO (yes I use the real name here but you will probably understand why).

CS:GO is one of the most game played on steam, the objective of this game is to be a counter-terrorist in a team of 5 players and kill the terrorists (5 players also in the competitive matches).

The game is actually protected by the Valve Anti-Cheat (VAC) system and an overwatch system (you can watch the game of a suspect and decide to voteban him or not).

To be honest with you, the VAC system is weak but the overwatch system is a good method, most of cheaters are banned with the overwatch method because you can’t really hide a powerful cheat (like an aimbot) but if you are smart, you can avoid to be banned if you hide your cheat (try to play with your wallhack without watch the ennemy behind a wall, play smart etc…).

There is also private cheats, a CS:GO player has been recently disqualified and banned from the FPL (Faceit Pro League), the FPL is the CS:GO Professionnal League (cash prizes are actually huge during the official tournaments) like you can see here:

https://www.esportsearnings.com/games/245-counter-strike-global-offensive/largest-tournaments

day0s was qualified in a month while some professional players had to play a few years to get there.

His cheat used the game scoreboard, actually in the game, when you press “TAB” you can see your scoreboad and use your mouse to click on a player name to recommand him, mute him etc…

But like you see in this movie, the cheat use the scoreboard to move the mouse cursor where the enemy is, day0s was able to know the exact position of his enemy each time he pressed TAB.

But this is only one the private cheats used by the CS:GO players, you can found some interesting projects on unknowncheats (like some hardware sonar cheats or sound based cheats):

Some players were accused and the main question was “how they cheated in lan where you can’t use your own computer and your own hardware ?” the answer is really simple:

Steam workshop allowed to use pictures with zipped file content, some players used a custom mouse with a cheat included, some players used their smartphone in usb directly on the lan computers etc…

There is also illegal sellers available on internet: http://hardwarecheats.com/

And finally here is an interview of supex0, the KQLY and Sf‘s custom cheats developer (two french CS:GO pro players banned few years ago):

Cash prizes is the main problem of the eSport scene and a real challenge for the anti-cheats industry.

I just presented the basic stuff here but there is also a cheats industry with advanced methods like you can see here:

Here is the details about the DMA leaks :

http://blog.frizk.net/2019/02/remote-live-memory-analysis-with-memory.html
https://github.com/EngineOwningSoftware/pcileech-webradar

Universal-ImGui-D3D11-Hook

Hello,

Today I decided to release a correct version of an ImGui menu directly hooked into a directx11 application.

The sources are available here: https://github.com/Sh0ckFR/Universal-ImGui-D3D11-Hook

I did that because my goal was to add some menus in games like GTA5, but sources available on the net was not really user/developer-friendly.

My work is based on: https://github.com/Rebzzel/Universal-D3D11-Hook

I just fixed some issues, added ImGui and added the mouse / keyboard InputHook.

If you want to use it, you can compile the project (don’t forget to add MinHook and ImGui correctly) and inject your dll in the targeted directx10/11 application.

The most important part is in d3d11hook:

D3D11_HOOK_API void ImplHookDX11_Present(ID3D11Device *device, ID3D11DeviceContext *ctx, IDXGISwapChain *swap_chain)
{
	if (GetAsyncKeyState(OpenMenuKey) & 0x1) {
		menu->IsOpen ? menu->IsOpen = false : menu->IsOpen = true;
	}

	menu->Render();
}

HRESULT __stdcall PresentHook(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags)
{
	std::call_once(g_isInitialized, [&]() {
		pSwapChain->GetDevice(__uuidof(g_pd3dDevice), reinterpret_cast<void**>(&g_pd3dDevice));
		g_pd3dDevice->GetImmediateContext(&g_pd3dContext);

		ImGui_ImplDX11_Init(g_hWnd, g_pd3dDevice, g_pd3dContext);
		inputHook->Init(g_hWnd);
	});

	ImplHookDX11_Present(g_pd3dDevice, g_pd3dContext, g_pSwapChain);

	return phookD3D11Present(pSwapChain, SyncInterval, Flags);
}

I suggest you to edit ImplHookDX11_Present only if you want to add your own code.

Have a good day 😉

Group Chat chiffré en AES256 avec NodeJS

Cher visiteur,

Il y a quelques temps de cela, je cherchais une messagerie chiffrĂ©e utilisable en groupe, aprĂšs avoir cherchĂ© un peu, testĂ© des messageries comme Wire (qui est pour le moment pour ma part une des plus secure que j’ai pu trouver mĂȘme si ça manque cruellement de fonctionnalitĂ©s), jabber avec otr ou mĂȘme omemo et bien d’autres.

Je me suis donc posĂ© la question “et si je m’amusais Ă  refaire un chat de groupe de façon chiffrĂ©” ?

Du coup je me suis permis de rĂ©aliser cette idĂ©e, bien sĂ»r il s’agit d’un PoC et beaucoup pensent qu’implĂ©menter soit mĂȘme une crypto est risquĂ© (ils ont trĂšs certainement raison).

J’ai donc dĂ©cidĂ© de me faire ma propre implĂ©mentation en utilisant comme vecteur d’initialisation (IV), des flux rss publics, de ce fait, l’AES change Ă  chaque fois qu’une nouvelle actualitĂ© est publiĂ©e sur le flux rss spĂ©cifiĂ©, pour sĂ©curiser un peu la chose, j’ai rajoutĂ© un salt Ă  communiquer entre clients avant la conversation, une meilleure solution serait d’utiliser des certificats mais Ă©changer tous les certificats entre chaque client est plutĂŽt fastidieux.

Server:

var io = require('socket.io').listen(1337);

var allClients = [];

io.sockets.on('connection', function (socket) {
	socket.on('send', function(data) {
		if(data.type == 'connected') {
			socket.nickname = data.content;
			allClients.push(socket);
			socket.broadcast.emit('send', { type : 'connected', content: socket.nickname + " is now connected" });
			socket.emit('send', { type : 'connected', content: socket.nickname + " is now connected" });
		} else if (data.type == 'list') {
			var nicknames = [];
			allClients.forEach(function(socket) {
				nicknames.push(socket.nickname)
			});
			socket.emit('send', { type : 'list', content: nicknames });
		} else if (data.type == 'message') {
			socket.broadcast.emit('send', { type : 'message', content: data.content });
		}
	});

	socket.on('disconnect', function() {
      	var i = allClients.indexOf(socket);
      	allClients.splice(i, 1);
      	socket.broadcast.emit('send', { type : 'disconnect', content: socket.nickname + " is now disconnected" });
   });
});

Client:

var server = 'http://localhost:1337';

var readline = require('readline');
var io = require('socket.io-client');
var socket;
var colors = require('colors');
var parser = require('rss-parser');
var sha256 = require('sha256');
var crypto = require('crypto'), algorithm = 'aes-256-ctr';

var rl = readline.createInterface(process.stdin, process.stdout);

var rss_link = 'https://www.lesechos.fr/rss/rss_une_titres.xml';
var aes_salt = 'YourSaltIfYouWant';

var nickname;
rl.question("Please enter a nickname: ", function(name) {
	nickname = name;
	socket = io.connect(server, {reconnect: true});
    socket.emit('send', { type: 'connected', content: name });

    socket.on('connect', function () { 
		socket.on('send', function(data) {
			if(data.type == 'connected') {
				console.log(colors.green(data.content));
				rl.prompt(true);
			} else if (data.type == 'list') {
				data.content.forEach(function(nickname) {
					console.log(colors.magenta(nickname));
				});
				rl.prompt(true);
			} else  if (data.type == 'message') {
				parser.parseURL(rss_link, function(err, parsed) {
					var iv = sha256(parsed.feed.entries[0].title + parsed.feed.entries[1].title);
					console.log(decrypt(iv + aes_salt, data.content));
					rl.prompt(true);
				});
			} else if (data.type == 'disconnect') {
				console.log(colors.red(data.content));
			}
		});

		rl.on('line', function (line) {
			if(line.indexOf('!help') > -1) {
				console.log(colors.yellow('!list -> Check who is online.'));
				rl.prompt(true);
			} else if(line.indexOf('!list') > -1) {
				socket.emit('send', { type: 'list' });
			} else {
				parser.parseURL(rss_link, function(err, parsed) {
					var iv = sha256(parsed.feed.entries[0].title + parsed.feed.entries[1].title);
					var message = encrypt(iv + aes_salt, nickname + " : " + line);
				  	socket.emit('send', { type: 'message', content: message });
					rl.prompt(true);
				});
			}
		});
	});
});

function encrypt(key, message) {
	var cipher = crypto.createCipher(algorithm,key)
  	var crypted = cipher.update(message,'utf8','hex')
  	crypted += cipher.final('hex');
	return crypted;
}

function decrypt(key, message) {
	var decipher = crypto.createDecipher(algorithm,key)
  	var decrypt = decipher.update(message,'hex','utf8')
  	decrypt += decipher.final('utf8');
	return decrypt;
}

DĂ©velopper avec NodeJS, Express, MongoDB, PugJS et Socket.IO

Cher visiteur,

Dans cet article, nous allons voir comment concevoir une application web plutÎt robuste avec NodeJS et Mongodb de façon trÚs simple et minimaliste.

Pour les plus nĂ©ophytes d’entre vous qui n’ont aucunes connaissances des routes nodejs, dĂ©pendances et j’en passe, le mieux est de commencer par la base de NodeJS via le tutoriel de mateo21 sur :

https://openclassrooms.com/courses/des-applications-ultra-rapides-avec-node-js

Tout d’abord, il vous faudra installer NodeJS ainsi que MongoDB

Sous Windows (Windows Server ou 10) :

Il suffit d’installer NodeJS en version LTS pour Windows x64 et MongoDB en version Windows Server, l’outil Ă©tant compatible aussi pour Windows 10.

Sous Linux :

apt-get install nodejs && apt-get install mongodb

Une fois l’environnement installĂ©, il vous suffit d’ouvrir un terminal ou une console Windows et taper cette commande pour vĂ©rifier l’installation (ceci vous retournera la version de nodejs installĂ© sur votre post) :

node -v

Pour commencer votre application, il vous faudra créer un répertoire et naviguer dedans via le terminal et la console et taper :

npm init

Cette commande aura pour objectif de vous poser des questions sur votre application, quelle est sa version, son auteur et j’en passe, elle finira ensuite par crĂ©er un fichier package.json qui contiendra toutes ces informations ainsi que les packages npm utilisĂ©s par votre application, les packages npm Ă©tant des extensions proposĂ©es par la communautĂ© NodeJS.

Votre package.json devrait maintenant ressembler Ă  ceci :

{
  "name": "application",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

La partie main avec “index.js” sera votre point d’entrĂ©e de l’application, du coup, le main de votre application sera “index.js” que vous devez crĂ©er en plaçant un code minimal dedans :

var express = require('express');
var app = express();
var pug = require('pug');
var io = require('socket.io').listen(app.listen(80));

conf = {
	lang: "fr",
	title: "Mon application",
	urlsocketio: "http://127.0.0.1:80/"
}

app.set('view engine', 'pug');

app.get('/', function(req, res) {
    res.render('index', { conf:conf } );
});

Il existe une autre façon de coder avec NodeJS si vous voulez rĂ©ellement de l’objet avec “TypeScript”, je ne l’aborderais pas ici mais libre Ă  vous de l’utiliser.

Pour faire fonctionner votre application, il vous faudra aussi installer les packages npm dont votre application a besoin, lancer cette commande dans le répertoire de votre application :

npm install express pug socket.io –save

Le –save permettant d’insĂ©rer vos packages dans le package.json ce qui permettra de dĂ©ployer votre application Ă  l’avenir avec un simple “npm install” sans avoir besoin de vous souvenir des noms de chaque package.

Maintenant vous devez crĂ©er un template Pug, Pug Ă©tant un langage simplifiĂ© du HTML qui a un gros avantage, c’est qu’on ne ferme aucune balise du coup le code est allĂ©gĂ©, prenons l’exemple d’une page HTML classique avec Bootstrap :

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Mon Application</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
  </head>
  <body>
    <h1>Hello, world!</h1>
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
      <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
    </body>
</html>

Celle-ci s’Ă©crira de cette façon avec Pug (faites un rĂ©pertoire views dans votre application avec un index.pug et copiez ce code dedans) :

doctype
html(lang="en")
	head
		meta(charset="utf-8")
		meta(http-equiv="X-UA-Compatible" content="IE=edge")
		meta(name="viewport" content="width=device-width, initial-scale=1")
		title Mon Application
		link(rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous")
	body
		h1 Hello, world!
		script(src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js")
		script(src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous")

Plus sympathique du coup pour de grandes pages html vous vous en doutez.

Si tout se passe bien, vous pouvez dĂšs maintenant lancer votre application nodejs en faisant un “node index.js”, si vous naviguez avec votre navigateur sur le port 80 comme dĂ©finit dans le code, vous verrez votre hello world.

Que faire maintenant ? on va bien entendu pousser la chose en codant un exemple de login avec un code de sécurité captcha et ainsi vous serez capable de coder vos propres applications.

Tout d’abord, il faut faudra modifier un peu votre index.js :

var express = require('express');
var app = express();
var pug = require('pug');
var io = require('socket.io').listen(app.listen(80));
var session = require('cookie-session');
var bodyParser = require('body-parser');
var urlencodedParser = bodyParser.urlencoded({ extended: false });
var sha256 = require('sha256');
var svgCaptcha = require('svg-captcha');

var MongoClient = require('mongodb').MongoClient;
var MongoClientURL = "mongodb://127.0.0.1:27017/mydatabase";

conf = {
	lang: "fr",
	title: "Mon application",
	urlsocketio: "http://127.0.0.1:80/"
}

app.use("/styles", express.static(__dirname + '/styles'));
app.set('view engine', 'pug');

app.use(session({secret: 'mysessionsecretpassphrase'}));
app.use(function(req, res, next){
    if (typeof(req.session.user) === 'undefined') {
        req.session.user = {};
    }
    next();
});

app.get('/', function(req, res) {
	if (Object.keys(req.session.user).length > 0) {
		username = req.session.user.username;
		res.render('panel', { conf:conf, user:req.session.user }  );
    } else {
        var captcha = svgCaptcha.create();
    	req.session.captcha = captcha.text;
        res.render('index', { conf:conf, "captcha":captcha });
    }
});

app.post('/login', urlencodedParser, function(req, res) {
	if(req.body.captcha === req.session.captcha) {
		MongoClient.connect(MongoClientURL, function(err, db) {
			db.collection('users').findOne({ 'username':req.body.username, 'password':sha256(req.body.password) }, function(err, result) {
				if(result !== null) {
	                req.session.user = result;
	            }
	            db.close();
	            res.redirect('/');
			});
		});
	} else {
		var captcha = svgCaptcha.create();
    	req.session.captcha = captcha.text;
    	res.render('index', { "captcha":captcha, "error":"The security code entered is not correct." });
	}
});

app.get('/logout', function (req, res) {
    delete req.session.user;
    res.redirect('/');
});

Comme vous pouvez le voir dans cette exemple, on a rajoutĂ© tout ce qui est nĂ©cessaire pour gĂ©rer une page de login avec captcha en se connectant au serveur mongodb local sur la base de donnĂ©es “mydatabase”, vu que nous avons rajoutĂ© des packages npm il va falloir les installer un Ă  un :

npm install cookie-session body-parser sha256 svg-captcha mongodb –save

À noter qu’il est possible d’avoir du sha512 ou d’autres algos pour chiffrer ses mots de passes, rĂ©fĂ©rez vous aux diffĂ©rents packages npm.

Connectons nous Ă  notre base de donnĂ©es mongodb, de base sur Windows, il vous faudra lancer l’exĂ©cutable se trouvant dans :

C:\Program Files\MongoDB\Server\3.4\bin\

Vous aurez à ce moment là deux exécutables :

– mongo.exe : Le client CLI permettant de se connecter Ă  notre serveur mongodb.
– mongod.exe : Le serveur en lui mĂȘme.

ExĂ©cutons mongod.exe pour lancer notre serveur et connectons nous Ă  l’aide de mongo.exe, vous devriez pouvoir exĂ©cuter des commandes dans celui-ci, voici un rĂ©capitulatif des diffĂ©rentes commandes importantes :

show dbs : Permet de voir les base de données disponibles.
use namedb : Permet d’utiliser une base de donnĂ©es, namedb Ă©tant le nom de la base de donnĂ©es que vous souhaitez utiliser (donc mydatabase)
show collections : Permet de voir les tables de la base de données sélectionnée.
db.nametable.insert() : Permet d’insĂ©rer des donnĂ©es dans une table, nametable Ă©tant notre nom de table.
db.nametable.find() : Permet de chercher des données dans une table.
db.nametable.remove() : Permet de supprimer des données dans une table.
db.nametable.update() : Permet de mettre à jour des données dans une table.
db.nametable.drop() : Permet de drop totalement la table.

Il existe une multitude de commandes, je vous conseille de vous rendre sur la documentation officielle pour plus de détails.

Nous allons donc créer notre utilisateur admin avec le mot de passe admin1234 :

use mydatabase
db.users.insert( { username:"admin", password:"ac9689e2272427085e35b9d3e3e8bed88cb3434828b43b86fc0596cad4c6e270" } );

Le hash Ă©tant notre sha256 de “admin1234”, si tout se passe bien, vous devriez avoir comme rĂ©sultat :


WriteResult({ "nInserted" : 1 })

Nous pouvons donc maintenant nous connecter Ă  notre panel, pour cela il va aussi falloir modifier votre index.pug :

doctype
html(lang=conf.lang)
	head
		meta(charset="utf-8")
		meta(http-equiv="X-UA-Compatible" content="IE=edge")
		meta(name="viewport" content="width=device-width, initial-scale=1")
		title #{conf.title}
		link(rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous")
		link(rel="stylesheet" href="styles/login.css")
	body
		section#section0.section
			div.container
				div.row
					div.col-md-12
						form.form-signin(action="login" method="post")
							h2.form-signin-heading Please sign in
							input.form-control(name="username" type="text" placeholder="Username..." required autofocus)
							input.form-control(name="password" type="password" placeholder="Password..." required)
							div#captcha !{captcha.data}
							input.form-control(style="margin-bottom: 0.5em;" name="captcha" type="text" placeholder="Security code..." required)
							button.btn.btn-lg.btn-primary.btn-block(type="submit") Sign in
							if error
								p#error #{error}
		script(src="https://code.jquery.com/jquery-3.2.1.min.js")
		script(src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous")

Et créer un fichier styles/login.css :

* {
    margin: 0;
    padding: 0;
}
body {
    padding-top: 40px;
    padding-bottom: 40px;
    background-color: #eee;
}
.form-signin {
    max-width: 330px;
    padding: 15px;
    margin: 0 auto;
}
.form-signin .form-signin-heading,
.form-signin .checkbox {
    margin-bottom: 10px;
}
.form-signin .checkbox {
    font-weight: normal;
}
.form-signin .form-control {
    position: relative;
    height: auto;
    -webkit-box-sizing: border-box;
       -moz-box-sizing: border-box;
            box-sizing: border-box;
    padding: 10px;
    font-size: 16px;
}
.form-signin .form-control:focus {
    z-index: 2;
}
.form-signin input[type="text"] {
    margin-bottom: -1px;
    border-bottom-right-radius: 0;
    border-bottom-left-radius: 0;
}
.form-signin input[type="password"] {
    margin-bottom: 10px;
    border-top-left-radius: 0;
    border-top-right-radius: 0;
}

#captcha {
    text-align: center;
}

#error {
    color: #ff0000;
    text-align: center;
}

Ainsi que notre panel.pug :

doctype
html(lang=conf.lang)
	head
		meta(charset="utf-8")
		meta(http-equiv="X-UA-Compatible" content="IE=edge")
		meta(name="viewport" content="width=device-width, initial-scale=1")
		title #{conf.title}
		link(rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous")
	body
		h1 hello #{user.username}

Vous avez maintenant un code avec un formulaire de login fonctionnel sous nodejs, express, mongodb et pugjs, qu’en est il de socket.io ?

Pour communiquer avec socket.io il nous suffit de modifier notre index.js en rajoutant :

io.sockets.on('connection', function (socket) {
	socket.emit('logged', "Le serveur vous salue !");

	socket.on('message', function (message) {
		console.log(message);
	});
});

socket.emit se chargera d’envoyer un message au client, socket.on attendra la rĂ©ponse du client, il est aussi possible d’utiliser socket.broadcast.emit() pour envoyer un message Ă  tous les clients en mĂȘme temps.

Pour réceptionner le message cÎté client, il vous suffira de rajouter ce javascript dans panel.pug :

doctype
html(lang=conf.lang)
	head
		meta(charset="utf-8")
		meta(http-equiv="X-UA-Compatible" content="IE=edge")
		meta(name="viewport" content="width=device-width, initial-scale=1")
		title #{conf.title}
		link(rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous")
	body
		h1 hello #{user.username}
		script(src="/socket.io/socket.io.js")
		script.
			var socket = io.connect('#{conf.urlsocketio}');
			socket.on('logged', function(message) {
				alert(message);
				socket.emit('message', "Salut serveur, je suis connecté !");
			});

VoilĂ , en espĂ©rant que cet article vous a permis d’avoir une bonne approche sur nodejs, mongodb, pugjs et express, vous ĂȘtes maintenant capable de dĂ©velopper en real time et de façon sĂ©curisĂ© (n’oubliez tout de mĂȘme pas que mongodb est certes du NoSQL mais NoSQL ne veut pas dire qu’il n’y a plus d’injections possibles, il vous faudra faire attention si vous utilisez les variables $where, $set et autres dans mongodb).

Une autre chose importante à savoir, de base mongodb autorise les connexions invités, vérifiez bien que votre serveur utilise son fichier de configuration pour ne pas autoriser de connexions distantes.

Voici les sources complÚtes de mon article légÚrement améliorées :

Sources

Pour dĂ©ployer la source, npm install 😉