Aug 26, 2011
Friday, August 26, 2011

เขียนบอทเกมด้วย AutoIt : Bot 7 แปลงชนิดข้อมูลใน Memory

     การสแกนเพื่อหาค่าต่างๆ โดยใช้โปรแกรม CE (Cheat Engine) ตามปกติแล้วคุณต้องเลือก Value Type เป็นแบบ 4 Bytes (ตัวเลขจำนวนเต็ม ไม่มีจุดทศนิยม) ซึ่งจะไม่ครอบคลุมค่าที่มีอยู่ภายในเกมทั้งหมด เพราะบางค่าจะเก็บข้อมูลเป็นแบบ Float (ตัวเลขจำนวนจริง ตัวเลขที่มีจุดทศนิยม) หรือ Char (ข้อมูลชนิดตัวอักษร) เมื่อสแกนค่าดังกล่าวใน CE ได้แล้ว หากจะนำมาเขียนสคริปต์ สำหรับอ่านหรือเขียนข้อมูลต้องเขียนคำสั่งเพิ่มเติม ต้องกำหนดชนิดของข้อมูลให้ตรงกัน เพื่อให้สคริปต์ AutoIt สามารถอ่านหรือเขียนค่าที่เป็นแบบ Float และ Char ได้อย่างไม่มีปัญหา

     เพื่อให้เข้าใจยิ่งขึ้นก่อนจะเริ่มเขียนสคริปต์ AutoIt เพื่อแปลงชนิดข้อมูลใน Memory คุณจะต้องดูรูปด้านล่างนี้ก่อน




    รูปด้านล่างจะแสดงข้อมูล 3 ชนิดที่ผมได้กล่าวมาข้างต้น เนื่องจากคำเรียกของชนิดข้อมูลระหว่างโปรแกรม CE และ AutoIt จะไม่เหมือนกัน ดังนั้นผมจึงต้องปรับความเข้าใจให้คุณได้รู้ก่อนคือ

4 Bytes = dword (ถ้าหากใช้ข้อมูลชนิดนี้ไม่ต้องตั้งค่าในสคริปต์ เพราะเป็นค่ามาตรฐานที่ใช้อยู่แล้ว)

Float = Float (ข้อมูลชนิดตัวเลขมีจุดทศนิยม)

Text = Char[ตัวเลข] (ตัวเลข คือจำนวนตัวอักษรที่ต้องการอ่านหรือเขียน ตั้งได้สูงสุดคือ 255)

     ต่อไปเป็นวิธีการเปลี่ยนรูปแบบข้อมูลการแสดงข้อมูลในโปรแกรม CE (จากแอดเดรสที่เราหาได้)

1. คลิกขวาบนแอดเดรสด้านล่างเลือกคำสั่ง Change Record > Type ดังรูปด้านล่างนี้ (หรือคลิกที่แอดเดรสแล้วกดปุ่ม Alt + Enter)



2. หน้าต่างเลือกชนิดข้อมูลจะปรากฏขึ้นมา ลองคลิกเลือกแบบ Float จะเห็นว่าคอลัมน์ Type ใน CE เปลี่ยนไปเป็น Float และค่าในคอลัมน์ Value ก็จะเปลี่ยนไปเป็นแบบ Float (เป็นข้อมูลชนิดตัวเลขทศนิยม)




    วิธีเขียนโปรแกรมเพื่ออ่านข้อมูลแบบ Float ทำได้ง่ายๆ ด้วยการใส่พารามิเตรอ์เข้าไปต่อท้ายคำสั่งเดิม คือ พิมพ์คำสั่ง ,“float” ลงไป (มีเครื่องหมายคอมม่า , คั่นทุกครั้ง) เช่น

_MemoryPointerRead($address, $memopen, $Offset,"float")


    ตามตัวอย่างนี้ผมแสดงการดึงเอาข้อมูลชนิด Float สำหรับการเขียนสคริปต์อ่าน Memory แบบที่ 2 (ในบทที่ 6) บางท่านสงสัยว่าแบบที่ 1 และ 3 ต้องเขียนอย่างไร คำตอบคือเขียนเหมือนกันครับคือพิมพ์คำสั่ง ,“float” ต่อท้ายสคริปต์ที่ใช้อ่านข้อมูลไปได้เลยครับ (วิธีพิมพ์ต่อท้ายดูจากสคริปต์ด้านล่างนี้)

ด้านล่างนี้สคริปต์แบบเต็มที่อ่านข้อมูลแบบ Float


#AutoIt3Wrapper_UseX64=n
#RequireAdmin
#include <NomadMemoryPSsix.au3>

Global $address = "0x00187F5C"
            
Global $Offset[2]
$Offset[0] = 0 ; ใส่ 0 เป็นค่าเริ่มต้นทุกครั้ง
$Offset[1] = 0x5578 ;ค่าออฟเซ็ต

$memopen = _MEMORYOPEN(ProcessExists("popcapgame1.exe")) ;เปลี่ยนชื่อไฟล์เกมส์

If $memopen = 0 Then
ConsoleWrite('ผิดพลาดไม่มีโปรแกรม =' & $memopen & @CRLF)
Exit
EndIf

;แปลงชนิดข้อมูลที่จะอ่านออกมาจาก Memory เป็นแบบ Float

$value = _MemoryPointerRead($address, $memopen, $Offset,"float")
ConsoleWrite('ค่าที่อ่านได้จากแอดเดรส ' & $value[0] & ' = ' & $value[1] & @CRLF)



_MEMORYCLOSE($memopen)

3. ลองกดปุ่ม F5 เพื่อดูผลลัพธ์การแสดงข้อมูลชนิด Float ก็จะเป็นดังภาพด้านล่างนี้



4. ต่อไปก็เป็นวิธีการเขียนข้อมูลแบบ Float ลงใน Memory ของเกม ซึ่งก็จะใช้วิธีเดียวกับการอ่านคือ พิมพ์คำสั่ง ,“float” ลงไปต่อท้ายสคริปต์สำหรับเขียนข้อมูล เช่น

_MemoryPointerWrite($address, $memopen, $Offset, "7",”float”)

ตัวอย่างสคริปต์แบบเต็ม สำหรับการเขียนข้อมูลแบบ Float ลงไปใน Memory เกม



#AutoIt3Wrapper_UseX64=n
#RequireAdmin
#include <NomadMemoryPSsix.au3>

Global $address = "0x00187F5C"

Global $Offset[2]
$Offset[0] = 0 ; ใส่ 0 เป็นค่าเริ่มต้นทุกครั้ง
$Offset[1] = 0x5578

$memopen = _MEMORYOPEN(ProcessExists("popcapgame1.exe")) ;เปลี่ยนชื่อไฟล์เกมส์
If $memopen = 0 Then
ConsoleWrite('ผิดพลาดไม่มีโปรแกรม =' & $memopen & @CRLF)
Exit
EndIf

$value = _MemoryPointerRead($address, $memopen, $Offset,"float")
ConsoleWrite('ค่าที่อ่านได้จากแอดเดรส ' & $value[0] & ' = ' & $value[1] & @CRLF)


_MemoryPointerWrite($address, $memopen, $Offset, "7",”float”)


_MEMORYCLOSE($memopen)


    ตัวอย่างสคริปต์ด้านบนเป็นการเขียนข้อมูลโดยใส่ค่า 7 แบบ Float ลงไปในหน่วยความจำ ข้อควรระวังอย่างมากในการเขียนค่าแบบอื่นก็คือ คุณสแกนหาค่าในโปรแกรม CE ชนิดใดแล้ว เวลาสร้างสคริปต์ AutoIt เพื่อเขียนค่า ก็ต้องกำหนดให้เขียนข้อมูลชนิดเดียวกันลงไปด้วย เช่น หากคุณสแกนค่าแบบปกติ (4 Byte) เมื่อได้ค่ามาแล้วก็ต้องสั่งเขียนแบบปกติ (4 Byte) อย่าเปลี่ยนไปเขียนแบบอื่น เพราะจะทำให้มีโอกาสเกิดข้อมูลผิดพลาด หรือกระทั่งทำให้โปรแกรมแฮงค์ได้ง่ายๆ



     เนื่องจากเกมแต่ละเกมจะมีการกำหนดลิมิตการใส่ค่าไม่เหมือนกัน (หรือกระทั่งกระหนดชนิดข้อมูลที่ใส่เข้าไปด้วย) การแปลงค่าใส่ข้อมูลที่ไม่ตรงกับชนิดข้อมูลที่สแกนได้ จะทำให้ค่ามากหรือน้อยกว่าระดับปกติที่ควรจะเป็น ตัวอย่างง่ายๆ ผมสแกนค่าแบบ 4 Byte เพื่อหาค่าพระอาทิตย์ในเกม Plants Vs Zombies แล้วสั่งเขียนข้อมูลแบบ Float ลงไป ผลลัพธ์ที่ได้ก็จะเหมือนภาพด้านล่างนี้ จะเห็นว่าตัวเลขเกินมาเป็นจำนวนมากเลยกรอบข้อมูลของเกมไป




     *** ขอย้ำอีกครั้งสำหรับสคริปต์ใน AutoIt ค่า 4 Byte ไม่ต้องเขียนพารามิเตอร์เพิ่มเพราะเป็นค่ามาตรฐานอยู่แล้ว คุณจะเขียนพารามิเตอร์เพิ่มเติม ในกรณีที่ต้องการอ่านเขียนค่าแบบ Float หรือ Char เท่านั้น


สำหรับการอ่านเขียนข้อมูลแบบ Char จะเขียนสคริปต์เหมือนกับ Float เพียงแต่มีการกำหนดจำนวนตัวอักษรที่ต้องการจะอ่านหรือเขียนต่อท้ายด้วยเท่านั้นเช่น

;อ่านข้อมูลชนิด Char ใน Memory จำนวน 64 ตัวอักษร

_MemoryPointerRead($address, $memopen, $Offset,"char[64]")



;เขียนข้อมูลชนิด Char ใน Memory จำนวน 32 ตัวอักษร

_MemoryPointerWrite($address, $memopen, $Offset, "สวัสดี PSsix","char[32]")




###จบแล้วครับ###

1 comments:

  1. งง งง แต่ก็ขอบคุณครับ อยากทราบวิธ๊หา Pointer เกมส์ออนไลน์ แล้วไม่ให้เด้งออกจากเกมส์อะครับ

    ต้องทำยังไง เหรอ ผมหาไม่ได้สักที ส่วนค่า Address คงที่นั้นเราต้องหายังไง ครับ

    แล้วค่าโปรที่ทำให้ตัวละครเรา ขยับ (เคลื่อนที่ได้เร็ว กว่าคนอื่นต้องทำไงอะคัรบ)

    ลบกวนพี่ๆ Pssix.blogspot.com แห่งนี้ช่วยแนะนำหน่อยครับ มีค่าเนื่อยให้

    ขอแบบเต็มๆไม่เกรียน Thaihack_2012@admin.in.th ช่วยหน่อยนะครับ

    ReplyDelete

    ส่วนนี้สำหรับแสดงความคิดเห็นทั่วไป สอบถามปัญหาตั้งถามได้ที่ฟอรั่ม


>>> [โปรดอ่าน] เนื่องจาก บทความการใช้งานบางโปรแกรมได้โฟสไปนานแล้ว
โปรแกรมอาจมีการอัปเดท วิธีการใช้งาน อาจใช้ไม่ได้ หรือมีวิธีที่ง่ายกว่าในเวอร์ชั่นใหม่
หากคุณพบว่าวิธีการใช้งานไม่ตรงกับบทความในบล็อกนี้ สามารถแนะนำเพิ่มเติมได้ครับ