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
![Smile :)](./images/smilies/icon_e_smile.gif)
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.