Here it is! The third and final guide in my small series relating to the Silkroad proxy project. From here you will learn how to make a simple clientless that can spawn in game using the edxSilkroadProxy. Included is support for character listing and server stats. Be sure to read through the entire guide and code before trying to make your own version!
Using edxSilkroadProxy to Create a Simple AutoIt Clientless
I. Purpose
The purpose of this guide is to show how limitless development is with the right tools at our disposal. For this guide, we will be using the edxSilkroadProxy project as the main driving force behind a simple clientless built in AutoIt. The clientless will be able to request and display the server stats, process the character listing packet, and login to the world server. It might not seem like much, but remember we are using AutoIt to demonstrate how easy the task is due to how our proxy is setup.
You can use any language you wish though as long as it supports the Winsock API. This clientless will allow you to login, but that’s as far as it goes. If you want to make your own logger or power level tool or whatever, a lot more programming is needed. However, the basics of what you need to do are shown. Let’s get started!
II. Requirements
This guide uses the “A Simple Silkroad Proxy Reference” guide previously posted. You will need to have read that guide and downloaded the project files so you have the edxSilkroadProxy to run. While you do not have to fully understand how the proxy works, it helps a lot in being able to know what you have to code in the clientless.
As the title mention, this guide will use AutoIt, so you need to download the latest version and get it installed. Only the built in functions are used in my code so you will not have to download any extra modules. You can also port the code to another language if you wish. I just used AutoIt to really make a point about the importance of design and making life easier through creative means.
III. Theory
The edxSilkroadProxy is designed to allow us to make clientless programs easier. First, we do not have to worry about any packet encryption or security bytes. This immediately makes the task ten times easier since we can just work with raw packets and send them directly to the proxy. Likewise when we are processing packets, we just parse them all as unencrypted and that’s it.
At this point, we need to look at which packets we do have to handle with the proxy in order to make our clientless. The proxy handles the handshake packets, 0x5000, so our clientless can ignore those. The handshake response packets, 0x9000 and 0x2001, are also handled for us. When the clientless receives the 0x2001 from the server, it is our job to send the 0x6100 reply packet which includes some information about our Silkroad version.
Assuming we send the right version the server is expecting, we will eventually get the patch version information via 0x600D. We can ignore those in our clientless. The proxy will request the server stats for us, so we do not have to initially request the server stats ourselves. If we want updated server stats though, then we can send the 0x6101 packet to request the stats.
Last but not least, the proxy handles the ping packet, 0x2002 for us so we do not have to setup our own timer to send it when it’s necessary (every 5 seconds there is not another packet sent). As you can see, we don’t have that much work in front of us! All we have to do is send one packet to be able to get to the point of being able to login. Once we are ready to login, we just have to send the login packet, 0x6102, once. For ISRO the proxy will handle the autologin logic for us. For other Silkroads, you have to send the login packet yourself again as needed based on server traffic or some error code.
When you get the results of the login packet, 0xA102, you need to parse the data if it’s successful to get the destination IP/Port to connect to. The proxy will have sent you a localhost address to connect to and will handle the remote world server address itself. Note that all you have to do is connect to the new IP/Port, you don’t have to handle anything else because the proxy does it for you!
When the server sends the world server login confirmation packet, 0xA103, it is your job to then request the character listing using the current opcode. From here, you can parse the character listing to get the available characters to login. When you are ready to login, you send the packet for the character selection using the current opcode. You have to be sure to parse the response packet for the character listing as well to make sure there was not an error selecting the character (wrong name, being deleted, etc…).
Once we join the world server, we will receive a lot of packets. You will want to look into parsing them as you need them for your programs. The player listing packet is long and not easy to parse. For this guide, we will ignore all of these packets and simple wait for the character id packet which comes bundled with the game time information. When we receive that packet, we will send the spawn opcode to join the world server!
Congratulations! You now have a simple clientless that can login to the world server. It will just stand there and not do anything, but it will stay connected since the proxy handle the ping packet. From here, you would code in your own clientless logic by parsing packets and responding to commands.
Be sure to read this theory section over a few times so you can follow the AutoIt code. The AutoIt code shows almost the minimal amount of packets you need to handle to make your own clientless. Be sure to read the comments as well!
Just for some final notes, the proxy does not handle the image code, so you will not be able to use the clientless on those Silkroad versions which still have an image code unless you use my old Image Code work and integrate it into the proxy or your own clientless. For CSRO, which uses a driver in the client to prevent clientless, you won’t get too far on that version either since you would need to crack their security first. If anything though, you can at least make clientless Server Stats programs
IV. Implementation
The complete code to the clientless is included. It will work fine for ISRO 1.205 but will need updating for future Silkroad versions where the opcodes change. The upcoming Legend4+ patch appears to change the opcodes so do not use this with old opcodes to avoid a ban.
If you start looking at the logic I used for packet building and parsing, it’s pretty neat. Rather than using traditional methods that complicate the code, I came up with this approach to easily work with the packet information. This code is mine and any resemble to other code on the net is purely coincidental. This code is released under the public domain and you can use it however you need to without any restrictions from me.
Code:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3>
#include <StaticConstants.au3>
#include <string.au3>
Global $controlArray[37][5]
Global $globalParseIndex = 0
Global $globalParseSize = 0
Global $globalParseBuffer = ""
Global $globalSendBuffer = ""
Global $globalSendSize = 0
Global $mainwindow = 0
Global $serverStatsTimer = 0
Global $doRequestStats = false
;SplashImageOn("edxLabs Proudly Presents...", "beeker2.jpg", 304, 378)
;Sleep(3000)
;SplashOff()
TCPStartup()
$socket = TCPConnect("127.0.0.1", 16000)
If $socket = -1 Then
MsgBox(64, "edxAutoitClientless", "Connection Failure.")
Exit
EndIf
$mainwindow = GUICreate("edxAutoItClientless", 800, 600)
GUISwitch($mainwindow)
$tab = GUICtrlCreateTab(10, 10, 800 - 20, 600 - 20)
$tab0 = GUICtrlCreateTabItem("Home")
$tab1 = GUICtrlCreateTabItem("Server Stats")
For $i = 0 to 18
$controlArray[$i][0] = GUICtrlCreateInput("000", 20, 40 + $i * 20, 25, 20)
$controlArray[$i][1] = GUICtrlCreateInput("Servername", 50, 40 + $i * 20, 90, 20)
$controlArray[$i][2] = GUICtrlCreateInput("0000", 140, 40 + $i * 20, 30, 20)
$controlArray[$i][3] = GUICtrlCreateInput("0000", 170, 40 + $i * 20, 30, 20)
$controlArray[$i][4] = GUICtrlCreateInput("00", 200, 40 + $i * 20, 20, 20)
Next
For $i = 19 to 36
$controlArray[$i][0] = GUICtrlCreateInput("000", 20 + 240, 40 + ($i - 19) * 20, 25, 20)
$controlArray[$i][1] = GUICtrlCreateInput("Servername", 50 + 240, 40 + ($i - 19) * 20, 90, 20)
$controlArray[$i][2] = GUICtrlCreateInput("0000", 140 + 240, 40 + ($i - 19) * 20, 30, 20)
$controlArray[$i][3] = GUICtrlCreateInput("0000", 170 + 240, 40 + ($i - 19) * 20, 30, 20)
$controlArray[$i][4] = GUICtrlCreateInput("00", 200 + 240, 40 + ($i - 19) * 20, 20, 20)
Next
$tab2 = GUICtrlCreateTabItem("Login")
GUICtrlCreateLabel("Account: ", 20, 43, 50)
Global $controlName = GUICtrlCreateInput("", 80, 40, 121, 20, BitOR($SS_LEFT, $ES_PASSWORD))
GUICtrlCreateLabel("Password: ", 20, 63, 50)
Global $controlPass = GUICtrlCreateInput("", 80, 60, 121, 20, BitOR($SS_LEFT, $ES_PASSWORD))
GUICtrlCreateLabel("Server: ", 20, 83, 50)
Global $controlServer = GUICtrlCreateCombo("xian", 80, 80, 121, 20)
GUICtrlSetData(-1, "aege|troy|athens|oasis|venice|greece|alps|olympus|tibet|babel|redsea|rome|sparta|********|pacific|alexander|persia|zeus|poseidon|hercules|odin|mercury|mars|saturn|venus|uranus|pluto|neptune|hera|gaia|eos|phoenix|ares|iris|titan|apollo") ; add other item snd set a new default
Global $controlLogin = GUICtrlCreateButton("Login!", 125, 105, 75)
Global $controlLog = GUICtrlCreateEdit("Welcome to edxAutoItClientless!" & @CRLF, 20, 150, 755, 420, $ES_AUTOVSCROLL + $WS_VSCROLL)
GUICtrlSetData($controlLog, "Made By: pushedx" & @CRLF, 1)
GUICtrlSetData($controlLog, "" & @CRLF, 1)
Global $controlCharacter = GUICtrlCreateCombo("Character Select", 300, 40, 121, 20)
Global $controlJoin = GUICtrlCreateButton("Let's Roll!", 430, 40, 75, 20)
GUISetState(@SW_SHOW)
$loginAttempts = 0
while 1
UpdateGui()
If @error Then
ExitLoop
Endif
if $doRequestStats and TimerDiff($serverStatsTimer) > 3000 Then
BeginPacket(0x6101)
EndPacket()
TCPSend($socket, GetPacket())
$doRequestStats = False ; Wait for the new packet to be received
Endif
$packetSize = TryReadWord($socket)
If @error == 0 Then
$packetOpcode = ReadWord($socket)
If @error Then
ExitLoop
Endif
$packetSecurity = ReadWord($socket)
If @error Then
ExitLoop
Endif
$packetData = ReadArray($socket, Dec($packetSize))
If @error Then
ExitLoop
Endif
;MsgBox(0, "", "$packetSize =" & $packetSize & chr(13) & "$packetOpcode =" & HexToStrWord($packetOpcode) & chr(13) & "$packetSecurity =" & $packetSecurity & chr(13) & $packetData)
Switch $packetOpcode
case "2001" ; Identify
BeginParse($packetData, Dec($packetSize))
$field1 = Dec(ParseWord()) ; length
$field2 = ParseAscii($field1)
if $field2 == "GatewayServer" then
BeginPacket(0x6100)
AppendByte(18) ; ISRO locale
AppendWord(9) ; length
AppendString("SR_Client") ; identity
AppendDword(205) ; version
EndPacket()
TCPSend($socket, GetPacket())
elseif $field2 == "AgentServer" then
; Nothing to do here
endif
case "A101" ; Server stats
$doRequestStats = true
BeginParse($packetData, Dec($packetSize))
$field1 = Dec(ParseByte())
$field2 = Dec(ParseByte())
$coreNameLength = Dec(ParseWord())
$coreName = ParseAscii($coreNameLength)
$nullTerm = ParseByte() ; null terminator
$nextServer = Dec(ParseByte())
$index = 0
while $nextServer == 1
$serverId = Dec(ParseWord())
$serverNameLength = Dec(ParseWord())
$serverName = ParseAscii($serverNameLength)
$serverCur = Dec(ParseWord())
$serverMax = Dec(ParseWord())
$serverState = Dec(ParseByte())
$nextServer = Dec(ParseByte())
GUICtrlSetData($controlArray[$index][0], $serverId)
GUICtrlSetData($controlArray[$index][1], $serverName)
GUICtrlSetData($controlArray[$index][2], $serverCur)
GUICtrlSetData($controlArray[$index][3], $serverMax)
GUICtrlSetData($controlArray[$index][4], $serverState)
$index = $index + 1
WEnd
$serverStatsTimer = TimerInit()
case "A102" ; Login result
BeginParse($packetData, Dec($packetSize))
$result = Dec(ParseByte())
if $result == 1 Then
$loginId = Dec(ParseDword())
$ipNameLength = Dec(ParseWord())
$ipName = ParseAscii($ipNameLength)
$ipPort = Dec(ParseWord())
AppendStatusText("You are ready to join the world server!")
AppendStatusText("Connecting to " & $ipName & ":" & $ipPort)
$socket = 0
$socket = TCPConnect($ipName, $ipPort) ; All we have to do is connect to the new IP/Port
$doRequestStats = False
Else
$result = Dec(ParseByte()) ; Some error, we need to handle them all in a real program
if $result == 5 Then
$loginAttempts = $loginAttempts + 1
AppendStatusText("Could not connect due to server traffic [" & $loginAttempts & "]")
Else
AppendStatusText("There was an error logging into this account")
EndIf
EndIf
case "A103" ; World server login result
BeginParse($packetData, Dec($packetSize))
$result = Dec(ParseByte())
if $result == 1 Then
AppendStatusText("You are now connected to the world server!")
BeginPacket(0x749F) ; Request character listing [TODO: Update each opcode change]
AppendByte(2) ; Request list
EndPacket()
TCPSend($socket, GetPacket())
EndIf
case "B49F" ; Char listing [TODO: Update each opcode change]
BeginParse($packetData, Dec($packetSize))
$operation = Dec(ParseByte())
if $operation == 2 then ; char listing
$result = Dec(ParseByte())
$charCount = Dec(ParseByte())
AppendStatusText("Found " & $charCount & " characters")
For $c = 1 to $charCount
$charType = Dec(ParseDword())
$charNameLength = Dec(ParseWord())
$charName = ParseAscii($charNameLength)
AppendStatusText("Found character: " & $charName)
GUICtrlSetData($controlCharacter, $charName, 1)
$charVol = Dec(ParseByte())
$charLvl = Dec(ParseByte())
AppendStatusText("Level: " & $charLvl)
$charExp = Dec(ParseQWord())
$charStr = Dec(ParseWord())
$charInt = Dec(ParseWord())
$charAttr = Dec(ParseWord())
$charHp = Dec(ParseDword())
$charMp = Dec(ParseDword())
AppendStatusText("HP/MP: " & $charHp & "/" & $charMp)
$doDelete = Dec(ParseByte())
if $doDelete == 1 then
$charMinsToDel = Dec(ParseDword())
EndIf
$unk1 = Dec(ParseWord())
$unk2 = Dec(ParseByte())
$itemCount = Dec(ParseByte())
AppendStatusText("This character has " & $itemCount & " items equipped.")
For $i = 1 to $itemCount
$itemId = Dec(ParseDword())
$itemPlus = Dec(ParseByte())
AppendStatusText("[" & $itemId & "][+ " & $itemPlus & "]")
Next
$itemCount = Dec(ParseByte())
AppendStatusText("This character has " & $itemCount & " avatar items equipped.")
For $i = 1 to $itemCount
$itemId = Dec(ParseDword())
$itemPlus = Dec(ParseByte())
AppendStatusText("[" & $itemId & "][+ " & $itemPlus & "]")
Next
AppendStatusText("")
Next
Endif
case "B7B0" ; Char selection (205) [TODO: Update each opcode change]
BeginParse($packetData, Dec($packetSize))
$result = Dec(ParseByte())
if $result == 1 then
AppendStatusText("Joining the game now...")
else
AppendStatusText("There was an error selecting this character. Please choose a different one.")
EndIf
case "332A" ; Char id and time (205) [TODO: Update each opcode change]
BeginParse($packetData, Dec($packetSize))
$charId = ParseDword()
$time_celestialPosition = Dec(ParseWord()) ; moon/sun
$time_hrs = Dec(ParseByte())
$time_mins = Dec(ParseByte())
AppendStatusText("My Character Id: " & $charId)
AppendStatusText("Time " & $time_hrs & ":" & $time_mins)
AppendStatusText("Celestial Position: " & $time_celestialPosition)
BeginPacket(0x328A) ; Send spawn packet [TODO: Update each opcode change]
EndPacket()
TCPSend($socket, GetPacket())
EndSwitch
ElseIf @error <> -3 Then
ExitLoop
Endif
wend
TCPShutdown()
;----------------------------------------------------------------------------------------------------
Func ReadByte($socket)
$lb = TCPRecv($socket, 1)
while $lb == ""
UpdateGui()
If @error Then
SetError(-2)
return 0
EndIf
$lb = TCPRecv($socket, 1)
If @error Then
SetError(-1)
return 0
EndIf
WEnd
return Hex(Binary($lb))
EndFunc
;----------------------------------------------------------------------------------------------------
Func ReadWord($socket)
$hb = TCPRecv($socket, 1)
while $hb == ""
UpdateGui()
If @error Then
SetError(-2)
return 0
EndIf
$hb = TCPRecv($socket, 1)
If @error Then
SetError(-1)
return 0
EndIf
WEnd
$lb = TCPRecv($socket, 1)
while $lb == ""
UpdateGui()
If @error Then
SetError(-2)
return 0
EndIf
$lb = TCPRecv($socket, 1)
If @error Then
SetError(-1)
return 0
EndIf
WEnd
return Hex(Binary($lb) & Binary($hb))
EndFunc
;----------------------------------------------------------------------------------------------------
Func TryReadWord($socket)
$hb = TCPRecv($socket, 1)
if $hb == "" Then
SetError(-3)
return 0
EndIf
$lb = TCPRecv($socket, 1)
while $lb == ""
UpdateGui()
If @error Then
SetError(-2)
return 0
EndIf
$lb = TCPRecv($socket, 1)
If @error Then
SetError(-1)
return 0
EndIf
WEnd
SetError(0)
return Hex(Binary($lb) & Binary($hb))
EndFunc
;----------------------------------------------------------------------------------------------------
Func ReadArray($socket, $count)
$data = ""
For $i = 1 to $count Step 1
UpdateGui()
If @error Then
SetError(-2)
return 0
EndIf
$data = $data & ReadByte($socket)
If @error Then
SetError(-1)
return 0
EndIf
Next
return $data
EndFunc
;----------------------------------------------------------------------------------------------------
Func HexToStrWord($var)
$len = StringLen($var)
if $len > 4 then
return StringRight($var, 4)
elseif $len == 4 then
return $var
elseif $len == 3 then
return "0" & $var
elseif $len == 2 then
return "00" & $var
elseif $len == 1 then
return "000" & $var
endif
EndFunc
;----------------------------------------------------------------------------------------------------
Func HexToStrDword($var)
$len = StringLen($var)
if $len > 8 then
return StringRight($var, 8)
elseif $len == 8 then
return $var
elseif $len == 7 then
return "0" & $var
elseif $len == 6 then
return "00" & $var
elseif $len == 5 then
return "000" & $var
elseif $len == 4 then
return "0000" & $var
elseif $len == 3 then
return "00000" & $var
elseif $len == 2 then
return "000000" & $var
elseif $len == 1 then
return "0000000" & $var
endif
EndFunc
;----------------------------------------------------------------------------------------------------
Func HexToStrByte($var)
$len = StringLen($var)
if $len > 2 then
return StringRight($var, 2)
elseif $len == 2 then
return $var
else ; Error condition
return "00"
endif
EndFunc
;----------------------------------------------------------------------------------------------------
Func BeginParse($buffer, $size)
$globalParseIndex = 1
$globalParseSize = $size
$globalParseBuffer = $buffer
EndFunc
;----------------------------------------------------------------------------------------------------
Func ParseByte()
$result = StringMid($globalParseBuffer, $globalParseIndex, 2)
$globalParseIndex = $globalParseIndex + 2
return $result
EndFunc
;----------------------------------------------------------------------------------------------------
Func ParseWord()
$low = ParseByte()
$hi = ParseByte()
return $hi & $low
EndFunc
;----------------------------------------------------------------------------------------------------
Func ParseDword()
$low = ParseWord()
$hi = ParseWord()
return $hi & $low
EndFunc
;----------------------------------------------------------------------------------------------------
Func ParseQWord()
$low = ParseDword()
$hi = ParseDword()
return $hi & $low
EndFunc
;----------------------------------------------------------------------------------------------------
Func ParseAscii($length)
$result = StringMid($globalParseBuffer, $globalParseIndex, $length * 2)
$globalParseIndex = $globalParseIndex + ($length * 2)
$len = StringLen($result)
$strResult = ""
For $i = 1 to $len Step 2
$strResult = $strResult & Chr(Dec(StringMid($result, $i, 2)))
Next
return $strResult
EndFunc
;----------------------------------------------------------------------------------------------------
Func ParseUnicode($length)
$result = StringMid($globalParseBuffer, $globalParseIndex, $length * 4)
$globalParseIndex = $globalParseIndex + ($length * 4)
$len = StringLen($result)
$strResult = ""
For $i = 1 to $len Step 4
$strResult = $strResult & ChrW(Dec(StringMid($result, $i, 4)))
Next
return $strResult
EndFunc
;----------------------------------------------------------------------------------------------------
Func BeginPacket($opcode)
$globalSendBuffer = ""
$globalSendSize = 0
$sOpcode = HexToStrWord(Hex($opcode))
$globalSendBuffer = StringMid($sOpcode, 3, 2) & StringMid($sOpcode, 1, 2)
$globalSendBuffer = $globalSendBuffer & "0000" ; Security bytes
;MsgBox(0, "", $globalSendBuffer)
EndFunc
Func AppendByte($value)
$sValue = HexToStrByte(Hex($value))
$globalSendBuffer = $globalSendBuffer & $sValue
$globalSendSize = $globalSendSize + 1
EndFunc
Func AppendWord($value)
$sValue = HexToStrWord(Hex($value))
$globalSendBuffer = $globalSendBuffer & StringMid($sValue, 3, 2) & StringMid($sValue, 1, 2)
$globalSendSize = $globalSendSize + 2
EndFunc
Func AppendDword($value)
$sValue = HexToStrDword(Hex($value))
$globalSendBuffer = $globalSendBuffer & StringMid($sValue, 7, 2) & StringMid($sValue, 5, 2) & StringMid($sValue, 3, 2) & StringMid($sValue, 1, 2)
$globalSendSize = $globalSendSize + 4
EndFunc
Func AppendString($value)
For $i = 1 to StringLen($value) Step 1
$xh = StringMid($value, $i, 1)
$sValue = HexToStrByte(Hex(Asc($xh)))
$globalSendBuffer = $globalSendBuffer & $sValue
$globalSendSize = $globalSendSize + 1
Next
EndFunc
Func EndPacket()
$sSize = HexToStrWord(Hex($globalSendSize))
$globalSendBuffer = (StringMid($sSize, 3, 2) & StringMid($sSize, 1, 2)) & $globalSendBuffer
;MsgBox(0, "", $globalSendBuffer)
EndFunc
Func GetPacket()
return _HexToString($globalSendBuffer)
EndFunc
;----------------------------------------------------------------------------------------------------
Func UpdateGui()
$msg = GUIGetMsg()
Select
Case $msg = $GUI_EVENT_CLOSE
SetError(-2)
Return
Case $msg = $controlJoin
$n = GUICtrlRead($controlCharacter, 1)
if StringLen($n) == 0 then
$n = GUICtrlRead($controlCharacter)
if StringLen($n) == 0 then
MsgBox(0, "", "Please choose a Character")
return
endif
endif
if StringCompare($n, "Character Select") == 0 then
MsgBox(0, "", "Please choose a Character")
return
endif
BeginPacket(0x77B0) ; [TODO: Update each opcode change]
AppendWord(StringLen($n))
AppendString($n)
EndPacket()
TCPSend($socket, GetPacket())
AppendStatusText("Attempting to login with character: " & $n)
Case $msg = $controlLogin
$n = GUICtrlRead($controlName)
if StringLen($n) == 0 then
MsgBox(0, "", "Please enter an Account")
return
endif
$p = GUICtrlRead($controlPass)
if StringLen($p) == 0 then
MsgBox(0, "", "Please enter a Password")
return
endif
$s = GUICtrlRead($controlServer)
;MsgBox(0, "", $n & " " & $p & " " & $s)
$doRequestStats = False
BeginPacket(0x6102)
AppendByte(18)
AppendWord(StringLen($n))
AppendString($n)
AppendWord(StringLen($p))
AppendString($p)
AppendWord(ServerToId($s))
EndPacket()
TCPSend($socket, GetPacket())
EndSelect
EndFunc
;----------------------------------------------------------------------------------------------------
Func ServerToId($server)
if StringCompare($server, "xian") == 0 Then
return 65
Endif
if StringCompare($server, "aege") == 0 Then
return 74
Endif
if StringCompare($server, "troy") == 0 Then
return 76
Endif
if StringCompare($server, "athens") == 0 Then
return 94
Endif
if StringCompare($server, "oasis") == 0 Then
return 96
Endif
if StringCompare($server, "venice") == 0 Then
return 102
Endif
if StringCompare($server, "greece") == 0 Then
return 107
Endif
if StringCompare($server, "alps") == 0 Then
return 113
Endif
if StringCompare($server, "olympus") == 0 Then
return 114
Endif
if StringCompare($server, "tibet") == 0 Then
return 132
Endif
if StringCompare($server, "babel") == 0 Then
return 134
Endif
if StringCompare($server, "redsea") == 0 Then
return 150
Endif
if StringCompare($server, "rome") == 0 Then
return 151
Endif
if StringCompare($server, "sparta") == 0 Then
return 152
Endif
if StringCompare($server, "********") == 0 Then
return 156
Endif
if StringCompare($server, "pacific") == 0 Then
return 159
Endif
if StringCompare($server, "alexander") == 0 Then
return 162
Endif
if StringCompare($server, "persia") == 0 Then
return 165
Endif
if StringCompare($server, "zeus") == 0 Then
return 166
Endif
if StringCompare($server, "poseidon") == 0 Then
return 174
Endif
if StringCompare($server, "hercules") == 0 Then
return 178
Endif
if StringCompare($server, "odin") == 0 Then
return 179
Endif
if StringCompare($server, "mercury") == 0 Then
return 180
Endif
if StringCompare($server, "mars") == 0 Then
return 181
Endif
if StringCompare($server, "saturn") == 0 Then
return 182
Endif
if StringCompare($server, "venus") == 0 Then
return 183
Endif
if StringCompare($server, "uranus") == 0 Then
return 187
Endif
if StringCompare($server, "pluto") == 0 Then
return 188
Endif
if StringCompare($server, "neptune") == 0 Then
return 190
Endif
if StringCompare($server, "hera") == 0 Then
return 191
Endif
if StringCompare($server, "gaia") == 0 Then
return 194
Endif
if StringCompare($server, "eos") == 0 Then
return 204
Endif
if StringCompare($server, "phoenix") == 0 Then
return 205
Endif
if StringCompare($server, "ares") == 0 Then
return 206
Endif
if StringCompare($server, "iris") == 0 Then
return 207
Endif
if StringCompare($server, "titan") == 0 Then
return 208
Endif
if StringCompare($server, "apollo") == 0 Then
return 209
Endif
EndFunc
;----------------------------------------------------------------------------------------------------
; Wrapper function to make life a little easier
Func AppendStatusText($text)
GUICtrlSetData($controlLog, $text & @CRLF, 1)
EndFunc
;----------------------------------------------------------------------------------------------------


V. Conclusion
Hopefully by now, you can understand how important design is. By designing our proxy in such a way that it handles the “tough” stuff for Silkroad, we can make programs in any language we want that are not limited by our ability to implement the Silkroad security in those languages. Furthermore, with a little creativity, you can see how easy it is to use AutoIt for a packet based program that looks pretty much like a C++ program would. There are some serious limitations to the language, but what you can really do with it just lies in your ability to program with it.
Study the code and the theory so you can take the concepts shown here and apply them into your own language. I’ve made a simple clientless in C#, C++, and AutoIt now using this approach and a friend has made them in VB.net and Java. Anything is doable, you just have to take the time and do it!
That wraps up this guide and the mini series. The first guide in the series showed us a simple proxy we can use for Silkroad. The second guide showed how to setup our own hook to use the client with the proxy. This third and final guide shows us how we can use a clientless with the proxy. There is still a lot of work that needs to be done though, so don’t stop here!
Drew “pushedx” Benton
edxLabs






