I'm releasing releasing my ps_login fix and a tutorial how to do it.
1. Find the code which works with the userid or password so we can get their address. The userid has a max length of 32 so after finding the user or pw address is enough.
The address in my ps_login is 00404A7C.
Code:
MOV CL,BYTE PTR DS:[EAX]
ADD EAX,1
TEST CL,CL
JNZ SHORT ps_login_beforefix.00404A73
SUB EAX,EDX <--- we will change this
PUSH EAX
PUSH ESI
LEA ECX,[ESP+1C]
CALL ps_login_beforefix.SMD5::MD5
2. (You can skip it) Test with cheatengine. I wrote this script auto assembly script for testing, we will edit this into to the ps_login later on.
Code:
alloc(jmpfilter,4096) //our mem
alloc(pwad,4) //pw address
alloc(userad,4) //user address
label(idLoop)
label(filterPw)
label(validChar)
label(invalidChar)
label(filterPw)
label(pwLoop)
label(validPw)
label(invalidPw)
label(afterFilter)
label(originalcode)
label(exit)
label(returnhere)
jmpfilter:
mov [userad],esi
sub [userad],20
mov [pwad],esi
//just to be sure
push esp
push ebp
push eax
push ebx
push ecx
push edx
push edi
push esi
// gain access to UserID string DS:ESI
mov esi,[userad]
// loop on char
idLoop:
mov al,BYTE PTR:[esi]
cmp al,0 // end of string?
je filterPw
cmp al,30 // '0'
jl invalidChar // chars lower than '0' are invalid
cmp al,39 // '9'
jle validChar // chars in '0'..'9' are valid
cmp al,40 // '@'
jl invalidChar // chars in 3A..3F are invalid
cmp al,5A // 'Z'
jle validChar // chars '@'..'Z' are valid
cmp al,61 // 'a'
jl invalidChar // chars in 5B..60 are invalid
cmp al,7E // '~'
jg invalidChar // chars after '~' are invalid
// process next char
validChar:
inc esi
jmp idLoop
// replace invalid char by 0 (new end of string)
invalidChar:
mov BYTE PTR:[esi],0
jmp filterPw
filterPw:
// gain access to Password string DS:ESI
mov esi,[pwad]
// loop on char
pwLoop:
mov al,BYTE PTR:[esi]
cmp al,0 // end of string?
je afterFilter
cmp al,30 // '0'
jl invalidPw // chars lower than '0' are invalid
cmp al,39 // '9'
jle validPw // chars in '0'..'9' are valid
cmp al,40 // '@'
jl invalidPw // chars in 3A..3F are invalid
cmp al,5A // 'Z'
jle validPw // chars '@'..'Z' are valid
cmp al,61 // 'a'
jl invalidPw // chars in 5B..60 are invalid
cmp al,7E // '~'
jg invalidPw // chars after '~' are invalid
// process next char
validPw:
inc esi
jmp pwLoop
// replace invalid char by 0 (new end of string)
invalidPw:
mov BYTE PTR:[esi],0
afterFilter:
//Restore registers
pop esi
pop edi
pop edx
pop ecx
pop ebx
pop eax
pop ebp
pop esp
originalcode:
sub eax,edx
push eax
push esi
lea ecx,[esp+1C]
exit:
jmp returnhere
"ps_login.exe"+4A7C:
jmp jmpfilter
nop
nop
nop
returnhere:
3. Now that we have a working code the next step will be editing it into the ps_login.
Look for a larger empty region. I looked for this code:
Address Hex dump Command
00440748 > \54 PUSH ESP
00440749 . 55 PUSH EBP
0044074A . 50 PUSH EAX
0044074B . 53 PUSH EBX
0044074C . 51 PUSH ECX
0044074D . 52 PUSH EDX
0044074E . 57 PUSH EDI
0044074F . 56 PUSH ESI
00440750 . 83EE 20 SUB ESI,20
00440753 > 8A06 MOV AL,BYTE PTR DS:[ESI]
00440755 . 3C 00 CMP AL,0
00440757 . 74 1E JE SHORT ps_login.00440777
00440759 . 3C 30 CMP AL,30
0044075B . 7C 17 JL SHORT ps_login.00440774
0044075D . 3C 39 CMP AL,39
0044075F . 7E 10 JLE SHORT ps_login.00440771
00440761 . 3C 40 CMP AL,40
00440763 . 7C 0F JL SHORT ps_login.00440774
00440765 . 3C 5A CMP AL,5A
00440767 . 7E 08 JLE SHORT ps_login.00440771
00440769 . 3C 61 CMP AL,61
0044076B . 7C 07 JL SHORT ps_login.00440774
0044076D . 3C 7E CMP AL,7E
0044076F . 7F 03 JG SHORT ps_login.00440774
00440771 > 46 INC ESI
00440772 .^ EB DF JMP SHORT ps_login.00440753
00440774 > C606 00 MOV BYTE PTR DS:[ESI],0
00440777 > 8B34E4 MOV ESI,DWORD PTR SS:[ESP]
0044077A > 8A06 MOV AL,BYTE PTR DS:[ESI]
0044077C . 3C 00 CMP AL,0
0044077E . 74 1E JE SHORT ps_login.0044079E
00440780 . 3C 30 CMP AL,30
00440782 . 7C 17 JL SHORT ps_login.0044079B
00440784 . 3C 39 CMP AL,39
00440786 . 7E 10 JLE SHORT ps_login.00440798
00440788 . 3C 40 CMP AL,40
0044078A . 7C 0F JL SHORT ps_login.0044079B
0044078C . 3C 5A CMP AL,5A
0044078E . 7E 08 JLE SHORT ps_login.00440798
00440790 . 3C 61 CMP AL,61
00440792 . 7C 07 JL SHORT ps_login.0044079B
00440794 . 3C 7E CMP AL,7E
00440796 . 7F 03 JG SHORT ps_login.0044079B
00440798 > 46 INC ESI
00440799 .^ EB DF JMP SHORT ps_login.0044077A
0044079B > C606 00 MOV BYTE PTR DS:[ESI],0
0044079E > 5E POP ESI
0044079F . 5F POP EDI
004407A0 . 5A POP EDX
004407A1 . 59 POP ECX
004407A2 . 5B POP EBX
004407A3 . 58 POP EAX
004407A4 . 5D POP EBP
004407A5 . 5C POP ESP
004407A6 . 29D0 SUB EAX,EDX
004407A8 . 50 PUSH EAX
004407A9 . 56 PUSH ESI
004407AA . 8D4CE4 1C LEA ECX,[ESP+1C]
004407AE .^ E9 D142FCFF JMP ps_login.00404A84
Notice the difference between this and CE code. Aside from the labels and such there's a modified part.
SUB ESI,20
As esi contains the start address of the password, we get the start address of the userid by subtracting 20h from esi.
20h (32) is the length of the userid.
MOV ESI,DWORD PTR SS:[ESP]
Because we didn't allocate memory like in CE we make use of the esi register that we pushed into the stack to regain the password address.
Make sure the jumps points where they should in case you put this code on a different address.
Now we have to modify the command at the 00404A7C address to get our called.
At the address 00404A7C modify the command (assemble) SUB EAX,EDX to JMP [start address of our code]. In my case JMP ps_login.00440748 . Make sure the Fill rest with NOPs if turned on.
Save the work by right click Edit->Copy all modification to executable , right click in the newly opened window and select save file.
4. This ps_login passes the password to the usp_Try_GameLogin_Taiwan as an MD5 hash so modification to the sp_LoginSuccessCheck is necessary. (Of course the passwords needed to be hashed too and stored in enpassword)
Code:
set ANSI_NULLS OFF
set QUOTED_IDENTIFIER OFF
GO
/****** Object: Stored Procedure dbo.sp_OmgLoginSuccessCheck Script Date: 2008-6-7 18:29:10 ******/
-- =============================
-- @Rtn_Success : 1-Success , 0-Fail
-- =============================
ALTER PROCEDURE [dbo].[sp_LoginSuccessCheck]
@userid varchar(18),
@checkPassword varchar(32),
@Rtn_Success int OUTPUT
AS
BEGIN
IF EXISTS(Select * From users_master with (nolock) Where userid=@userid And enpassword=@checkPassword)
BEGIN
--Login Success
SET @Rtn_Success = 1
END
ELSE
BEGIN
--Login Fail
SET @Rtn_Success =- 1
END
RETURN @Rtn_Success
END
Special thanks to Castor for helping and reviewing my code.
****, you were faster than me :/ Great job That's so bad most of community doesnt care about knowledge anymore. If they have the fix that's enough for them.
Its not only from the storedprocess...
Its write with or without Account Does not Exist ^^
one Fix ?
Regard
Make sure that the username and the password doesnt contain characters like -_.() and so on, as they are filtered.
Also make sure that password is md5 hashed and stored in enpassword.
Got it, thank you very much, I am very grateful to you szobonya3
but I still have a question, how will inject the password md5 in php registration?
PHP Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml">
// Processar os dados POST. if(isset($_POST) && !empty($_POST)){ // Validar nome de usuário. if(empty($username)){ $errors[] = 'Por favor, forneça um nome de usuário.'; }else if(strlen($username) < 3 || strlen($username) > 16){ $errors[] = 'Nome de usuário deve ter entre 3 e 16 caracteres.'; }else if(ctype_alnum($username) === false){ $errors[] = 'Nome de usuário deve consistir de números e letras apenas.'; }else{ // Verifique se o nome já existe no banco de dados. $sql = "SELECT UserID FROM PS_UserData.dbo.Users_Master WHERE UserID = ?"; $stmt = odbc_prepare($GLOBALS['dbConn'],$sql); $args = array($username); if(!odbc_execute($stmt,$args)){ $errors[] = 'Não foi possível determinar se esse usuário já existe no banco de dados.'; }elseif($row = odbc_fetch_array($stmt)){ $errors[] = 'Nome de usuário já existe, por favor escolha um nome de usuário diferente.'; } }
// Validar a senha do usuário. if(empty($password)){ $errors[] = 'Por favor, forneça uma senha.'; }else if(strlen($password) < 3 || strlen($password) > 16){ $errors[] = 'A senha deve ter entre 3 e 16 caracteres.'; }else if($password != $password2){ $errors[] = 'As senhas não coincidem.'; }
// Validar reCAPTCHA. Isso é para evitar que alguém a criação da conta bots. $response = recaptcha_check_answer($recaptcha_private_key,$_SERVER['REMOTE_ADDR'],$_POST['recaptcha_challenge_field'],$_POST['recaptcha_response_field']); if(!$response->is_valid){ if($response->error == 'incorrect-captcha-sol'){ $errors['recaptcha'] = 'Resposta incorreta a reCAPTCHA'; }else{ $errors['recaptcha'] = $response->error; } }
// Persistir a nova conta para o banco de dados se há erros anteriores ocorreram. if(count($errors) == 0){ $sql = "INSERT INTO PS_UserData.dbo.Users_Master (UserID,Pw,JoinDate,Admin,AdminLevel,UseQueue,Status,Leave,LeaveDate,UserType,Point,EnPassword,UserIp,Email,UserCargo,PWName) VALUES (?,?,GETDATE(),0,0,0,0,0,GETDATE(),'N',0,'',?,1,1,1)"; $stmt = odbc_prepare($GLOBALS['dbConn'],$sql); $args = array($username,$password,$user_ip); if(odbc_execute($stmt,$args)){ $success = htmlentities("Conta {$username} criado com sucesso!"); }else{ // Isto significa que a declaração de inserção provavelmente não é válida para o seu banco de dados. Fixar a consulta ou corrigir o seu banco de dados, a sua escolha ;) $errors[] = 'Falha ao criar uma nova conta, por favor, tente novamente mais tarde'; } } } // Determinar que ver a mostrar. if($success === false){ require_once('register.view.php'); }else{ require_once('success.view.php'); } ?>
Got it, thank you very much, I am very grateful to you szobonya3
but I still have a question, how will inject the password md5 in php registration?
PHP Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml">
// Processar os dados POST. if(isset($_POST) && !empty($_POST)){ // Validar nome de usuário. if(empty($username)){ $errors[] = 'Por favor, forneça um nome de usuário.'; }else if(strlen($username) < 3 || strlen($username) > 16){ $errors[] = 'Nome de usuário deve ter entre 3 e 16 caracteres.'; }else if(ctype_alnum($username) === false){ $errors[] = 'Nome de usuário deve consistir de números e letras apenas.'; }else{ // Verifique se o nome já existe no banco de dados. $sql = "SELECT UserID FROM PS_UserData.dbo.Users_Master WHERE UserID = ?"; $stmt = odbc_prepare($GLOBALS['dbConn'],$sql); $args = array($username); if(!odbc_execute($stmt,$args)){ $errors[] = 'Não foi possível determinar se esse usuário já existe no banco de dados.'; }elseif($row = odbc_fetch_array($stmt)){ $errors[] = 'Nome de usuário já existe, por favor escolha um nome de usuário diferente.'; } }
// Validar a senha do usuário. if(empty($password)){ $errors[] = 'Por favor, forneça uma senha.'; }else if(strlen($password) < 3 || strlen($password) > 16){ $errors[] = 'A senha deve ter entre 3 e 16 caracteres.'; }else if($password != $password2){ $errors[] = 'As senhas não coincidem.'; }
// Validar reCAPTCHA. Isso é para evitar que alguém a criação da conta bots. $response = recaptcha_check_answer($recaptcha_private_key,$_SERVER['REMOTE_ADDR'],$_POST['recaptcha_challenge_field'],$_POST['recaptcha_response_field']); if(!$response->is_valid){ if($response->error == 'incorrect-captcha-sol'){ $errors['recaptcha'] = 'Resposta incorreta a reCAPTCHA'; }else{ $errors['recaptcha'] = $response->error; } }
// Persistir a nova conta para o banco de dados se há erros anteriores ocorreram. if(count($errors) == 0){ $sql = "INSERT INTO PS_UserData.dbo.Users_Master (UserID,Pw,JoinDate,Admin,AdminLevel,UseQueue,Status,Leave,LeaveDate,UserType,Point,EnPassword,UserIp,Email,UserCargo,PWName) VALUES (?,?,GETDATE(),0,0,0,0,0,GETDATE(),'N',0,'',?,1,1,1)"; $stmt = odbc_prepare($GLOBALS['dbConn'],$sql); $args = array($username,$password,$user_ip); if(odbc_execute($stmt,$args)){ $success = htmlentities("Conta {$username} criado com sucesso!"); }else{ // Isto significa que a declaração de inserção provavelmente não é válida para o seu banco de dados. Fixar a consulta ou corrigir o seu banco de dados, a sua escolha ;) $errors[] = 'Falha ao criar uma nova conta, por favor, tente novamente mais tarde'; } } } // Determinar que ver a mostrar. if($success === false){ require_once('register.view.php'); }else{ require_once('success.view.php'); } ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml">
// Processar os dados POST. if(isset($_POST) && !empty($_POST)){ // Validar nome de usuário. if(empty($username)){ $errors[] = 'Por favor, forneça um nome de usuário.'; }else if(strlen($username) < 3 || strlen($username) > 16){ $errors[] = 'Nome de usuário deve ter entre 3 e 16 caracteres.'; }else if(ctype_alnum($username) === false){ $errors[] = 'Nome de usuário deve consistir de números e letras apenas.'; }else{ // Verifique se o nome já existe no banco de dados. $sql = "SELECT UserID FROM PS_UserData.dbo.Users_Master WHERE UserID = ?"; $stmt = odbc_prepare($GLOBALS['dbConn'],$sql); $args = array($username); if(!odbc_execute($stmt,$args)){ $errors[] = 'Não foi possível determinar se esse usuário já existe no banco de dados.'; }elseif($row = odbc_fetch_array($stmt)){ $errors[] = 'Nome de usuário já existe, por favor escolha um nome de usuário diferente.'; } }
// Validar a senha do usuário. if(empty($password)){ $errors[] = 'Por favor, forneça uma senha.'; }else if(strlen($password) < 3 || strlen($password) > 16){ $errors[] = 'A senha deve ter entre 3 e 16 caracteres.'; }else if($password != $password2){ $errors[] = 'As senhas não coincidem.'; }
// Validar reCAPTCHA. Isso é para evitar que alguém a criação da conta bots. $response = recaptcha_check_answer($recaptcha_private_key,$_SERVER['REMOTE_ADDR'],$_POST['recaptcha_challenge_field'],$_POST['recaptcha_response_field']); if(!$response->is_valid){ if($response->error == 'incorrect-captcha-sol'){ $errors['recaptcha'] = 'Resposta incorreta a reCAPTCHA'; }else{ $errors['recaptcha'] = $response->error; } }
// Persistir a nova conta para o banco de dados se há erros anteriores ocorreram. if(count($errors) == 0){ $enpassword = md5($password); //modification $sql = "INSERT INTO PS_UserData.dbo.Users_Master (UserID,Pw,JoinDate,Admin,AdminLevel,UseQueue,Status,Leave,LeaveDate,UserType,Point,EnPassword,UserIp,Email,UserCargo,PWName) VALUES (?,?,GETDATE(),0,0,0,0,0,GETDATE(),'N',0,?,?,1,1,1)"; $stmt = odbc_prepare($GLOBALS['dbConn'],$sql); $args = array($username,$password,$enpassword,$user_ip); /*modification, remove $password variable if you dont want to keep the clean text and change $sql = "INSERT INTO PS_UserData.dbo.Users_Master (UserID,Pw,JoinDate,Admin,AdminLevel,UseQueue,Status,Leave,LeaveDate,UserType,Point,EnPassword,UserIp,Email,UserCargo,PWName) VALUES (?,'',GETDATE(),0,0,0,0,0,GETDATE(),'N',0,?,?,1,1,1)";*/ if(odbc_execute($stmt,$args)){ $success = htmlentities("Conta {$username} criado com sucesso!"); }else{ // Isto significa que a declaração de inserção provavelmente não é válida para o seu banco de dados. Fixar a consulta ou corrigir o seu banco de dados, a sua escolha ;) $errors[] = 'Falha ao criar uma nova conta, por favor, tente novamente mais tarde'; } } } // Determinar que ver a mostrar. if($success === false){ require_once('register.view.php'); }else{ require_once('success.view.php'); } ?>
Make sure that the username and the password doesnt contain characters like -_.() and so on, as they are filtered.
Also make sure that password is md5 hashed and stored in enpassword.
>They arent ^^ i will do via the process of Castor he was release the way to make it ^^ thanks
Hello, I am using this ps_login. Already tested the ps_login the nubness, and ps_login JuliPoli. and continue to invade my database. Now they are all the time editing my dbo.Chars table. Please, I'm desperate. Someone could help me?
ps_login hack how to 05/02/2020 - Shaiya PServer Guides & Releases - 7 Replies I'll show you how it was done
but first the fixs for it:
http://www.elitepvpers.com/forum/shaiya-pserver-g uides-releases/3525712-release-fixed-ps_login.html
http://www.elitepvpers.com/forum/shaiya-pserver-g uides-releases/3525341-release-ps_login-anti-injec tion.html
get a copy of working packet injector and attach to game.exe
before login send this packet
[Release]Fixed ps_login 12/16/2018 - Shaiya PServer Guides & Releases - 9 Replies Hello everyone,
As most of you might have remarked, I have not been active for a little over a month, being too busy with other things. I apologize to those I have ignored, I just needed some peace, and I still do, so please don't bother contacting me with any request for your server.
Recently, it was brought to my attention that I was doing some sort of SQL injection attacks on certain servers. I have to admit I had no idea that I did such things, it must have happened while I was...
[RELEASE] ps_login anti-injection 04/27/2015 - Shaiya PServer Guides & Releases - 28 Replies There you go, it won't accepte this injections from those bad people..
Yes, I payd for get it, I release it for free because Im a man who will never sell any files.
Virus Total Scan
Help me shaiya ps_login.exe attack!!! 12/13/2014 - Shaiya PServer Development - 3 Replies Help to fix a bug with ps-login.exe / Please everyone who can help write in skype:dolc.diables
HxD Code For Intering Ps_login database 06/23/2013 - Shaiya Hacks, Bots, Cheats & Exploits - 7 Replies Put this on Injection Coder To dirct in login database this is for all version shaiya code..
Ps_Login Database code
53 68 61 69 79 61 20 4C 6F 67 69 6E 20 53 65 72 76 65 72
Soon We will Release the Svnico Coder for all Pserver event shaiya korean will be affected of this Coder