Code: Select all
V Z40 a32 v
Code: Select all
V Z24 Z24 C
As a refresher, look up http://www.rubydoc.info/stdlib/core/Array%3Apack
So from that link you'll see that the packing string
Code: Select all
V Z40 a32 v
Code: Select all
V | Integer | 32-bit unsigned, VAX (little-endian) byte order
a | String | same as ``a'', except that null is added with *
Z | String | arbitrary binary string (null padded, count is width)
v | Integer | 16-bit unsigned, VAX (little-endian) byte order
Like I mentioned in the previous section as well as the wiki entry on the network subsystem, Ragnarok's packets are heralded by a packet switch (aka message ID). In this particular case we're interested in something called the "master_login" packet, which is "0A76" in phRO and thRO, and "0064" in iRO restart.
Time to do some code to test this out
But first, if you're in windows you'll need the Windows Subsystem for Linux https://msdn.microsoft.com/en-us/comman ... tall_guide so you can follow along. Mac users already have ruby installed, and Linux users can just use apt-get to install ruby.
You'll also need to install libmcrypt-dev in linux to make use of the cryptography library.
We're gonna need a few gems (which are libraries; code that has been packaged to be reused by other developers) installed, so type these in:
Code: Select all
gem install ruby-mcrypt
gem install hexdump
Code: Select all
require "socket"
require "mcrypt"
require "hexdump"
packet_switch = [0x0a76].pack("v")
version = [0x0018].pack("V")
username = "username".ljust(40, "\0")
password = "password".ljust(16, "\0")
crypt_key = [0x06, 0xA9, 0x21, 0x40, 0x36, 0xB8, 0xA1, 0x5B, 0x51, 0x2E, 0x03, 0xD5, 0x34, 0x12, 0x00, 0x06, 0x06, 0xA9, 0x21, 0x40, 0x36, 0xB8, 0xA1, 0x5B, 0x51, 0x2E, 0x03, 0xD5, 0x34, 0x12, 0x00, 0x06].pack("C32")
cipher = Mcrypt.new(:rijndael_256, :ecb, crypt_key, nil, :zeros)
password_rijndael = cipher.encrypt(password)
master_version = [0x000f].pack("v")
packet = packet_switch + version + username + password_rijndael + master_version
Hexdump.dump(packet) # dumps the packet to the screen
ip_address = "116.93.119.116" # replace with the correct ip address; this one is for phRO
ip_port = 6900 # same here, replace with the correct port
socket = TCPSocket.new ip_address, ip_port
puts "sending"
socket.write(packet)
puts "receiving"
data = socket.recvfrom(1024)
Hexdump.dump(data.pack("A*"))
data = socket.recvfrom(1024)
puts data.pack("H*")
Hexdump.dump(data.pack("A*"))
Code: Select all
ruby ragnarok.rb
Code: Select all
0> b5 01 fe ff ff ff fe ff ff ff 00 00 00 00 00 00 |................|
16> 00 00 |..|
0> 76 02 73 00 00 00 00 00 00 00 00 00 00 00 00 00 v.s.............
16> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ .......
32> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 64 ...............d
48> 00 00 00 74 5D 77 1E 94 11 54 68 6F 72 20 28 4E ...t]w...Thor (N
64> 65 77 29 00 00 00 00 00 00 00 00 00 00 7B 1A 00 ew)..........{..
80> 00 00 00 74 5D 78 86 94 11 4C 6F 6B 69 00 00 00 ...t]x...Loki...
96> 00 00 00 00 00 00 00 00 00 00 00 00 00 25 37 00 .............%7.
112> 00 00 00 ...
I understand that this is all so complicated with all the encryption and such, so next time let's try working on a less protected server, like iRO restart.