Java外掛開發入門示例

hyperzhen發表於2009-08-13
由於原文較長,圖又比較多,且CSDN部落格圖片目前無法外部訪問|||,所以僅發來部分,全文請去鄙人CSDN的部落格:[url]http://blog.csdn.net/cping1982[/url] ,希望51cto能早日提供部落格遷移功能……

示例執行結果如下圖:


package org.loon.test.os;

/**
* Copyright 2008
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* [url]http://www.apache.org/licenses/LICENSE-2.0[/url]
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* @project loonframework
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
import java.awt.Dimension;
import javax.swing.JButton;
import java.awt.Rectangle;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.EventQueue;
import java.awt.SystemColor;
import java.awt.Color;

import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.JLabel;

import org.loon.framework.os.ASM;
import org.loon.framework.os.OSProcess;


public class TestCallForm extends JFrame {

private static final long serialVersionUID = 1L;

private JPanel jContentPane = null;

private JButton btnHP = null;

private JButton btnHome = null;

private JButton btnBaseEax = null;

private JButton btnIce = null;

private JButton btnFire = null;

private JButton btnSP = null;

private JTextField txtIntPtr = null;

private JLabel jLabel = null;

public TestCallForm() {
super();
initialize();
}

private void initialize() {

this.setResizable(false);
this.setSize(238, 315);
this.setContentPane(getJContentPane());
this.setTitle("Java外掛開發入門示例");
this.setLocationRelativeTo(null);
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}

private JPanel getJContentPane() {
if (jContentPane == null) {
jLabel = new JLabel();
jLabel.setBounds(new Rectangle(30, 20, 180, 30));
jLabel.setForeground(Color.white);
jLabel.setText("暫存器EAX值(針對本機環境)");
jContentPane = new JPanel();
jContentPane.setLayout(null);
jContentPane.setSize(new Dimension(236, 241));
jContentPane.setBackground(SystemColor.activeCaption);
jContentPane.add(getBtnHP(), null);
jContentPane.add(getBtnHome(), null);
jContentPane.add(getBaseIntPtr(), null);
jContentPane.add(getBtnIce(), null);
jContentPane.add(getBtnFire(), null);
jContentPane.add(getBtnSP(), null);
jContentPane.add(getTxtIntPtr(), null);
jContentPane.add(jLabel, null);
}
return jContentPane;
}

private JButton getBtnHP() {
if (btnHP == null) {
btnHP = new JButton();
btnHP.setBounds(new Rectangle(15, 106, 95, 30));
btnHP.setText("吃血");
btnHP.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent e) {
clickEvent("hp");
}
});
}
return btnHP;
}

private JButton getBtnHome() {
if (btnHome == null) {
btnHome = new JButton();
btnHome.setBounds(new Rectangle(15, 195, 200, 30));
btnHome.setText("回城");
btnHome.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent e) {
clickEvent("home");
}
});
}
return btnHome;
}

private JButton getBtnIce() {
if (btnIce == null) {
btnIce = new JButton();
btnIce.setBounds(new Rectangle(120, 150, 95, 30));
btnIce.setText("冰系魔法");
btnIce.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent e) {
clickEvent("ice");
}
});
}
return btnIce;
}

private JButton getBtnFire() {
if (btnFire == null) {
btnFire = new JButton();
btnFire.setBounds(new Rectangle(15, 150, 95, 30));
btnFire.setText("火系魔法");
btnFire.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent e) {
clickEvent("fire");
}
});
}
return btnFire;
}

private JButton getBtnSP() {
if (btnSP == null) {
btnSP = new JButton();
btnSP.setBounds(new Rectangle(120, 106, 95, 30));
btnSP.setText("加藍");
btnSP.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent e) {
clickEvent("sp");
}
});
}
return btnSP;
}

private JButton getBaseIntPtr() {
if (btnBaseEax == null) {
btnBaseEax = new JButton();
btnBaseEax.setBounds(new Rectangle(15, 235, 200, 30));
btnBaseEax.setText("獲得本機EAX數值");
btnBaseEax.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent e) {
clickEvent("find");
}
});
}
return btnBaseEax;
}

private JTextField getTxtIntPtr() {
if (txtIntPtr == null) {
txtIntPtr = new JTextField();
txtIntPtr.setBounds(new Rectangle(18, 57, 199, 30));
txtIntPtr.setText("00D52070");
}
return txtIntPtr;
}

/**
* 觸發事件
*
* @param eventName
*/
private void clickEvent(final String eventName) {
int pid = OSProcess.findWindowProcessId("TForm1", "遊戲找CALL練習例項one");
if (pid == 0) {
JOptionPane.showMessageDialog(this, "您的遊戲程式尚未啟動,外掛無法載入!");
return;
}
int eaxPtr = 0;
try {
eaxPtr = ASM.getHexStringToInt(this.txtIntPtr.getText().trim());
} catch (Exception ex) {
JOptionPane.showMessageDialog(this, "暫存器數值設定格式有誤,外掛無法載入!");
return;
}
// 從基址獲取暫存器中eax數值
if ("find".equalsIgnoreCase(eventName)) {
this.txtIntPtr.setText(OSProcess.readProcessMemory(pid, 0x456D68));
}
// 例項化asm類以進行java與彙編混合操作
ASM asm = new ASM();

// 儲存所有暫存器,即全部進棧
asm._PUSHAD();
// 示例程式執行時,目標暫存器eax中的必備數值(PS:在我的機器上是00D52070,
// 而找Call測試程式作者提供的是00D51FE4,請自行查詢。錯誤時目標程式將崩潰。)
asm._MOV_EAX(eaxPtr);
// 吃紅
if ("hp".equalsIgnoreCase(eventName)) {
asm._MOV_EDX(0x453028);
asm._CALL(0x452E98);
}
// 吃藍
else if ("sp".equalsIgnoreCase(eventName)) {
asm._MOV_EDX(0x453040);
asm._CALL(0x452E98);
}
// 火系魔法
else if ("fire".equalsIgnoreCase(eventName)) {
asm._MOV_ECX(0x45309C);
asm._MOV_EDX(2);
asm._CALL(0x452DF8);
// 冰系魔法
} else if ("ice".equalsIgnoreCase(eventName)) {
asm._MOV_ECX(0x45307C);
asm._MOV_EDX(1);
asm._CALL(0x452DF8);
}
// 回城
else if ("home".equalsIgnoreCase(eventName)) {
asm._MOV_EDX(0x45305C);
asm._CALL(0x452E98);
}
// 還原所有暫存器,即全部出棧
asm._POPAD();
// 結尾標記,操作開始執行
asm._RET();

// 要求進行程式碼注入的程式id
asm.doInject(pid);

}


public static void main(String[] args) {

EventQueue.invokeLater(new Runnable() {
public void run() {
TestCallForm callForm = new TestCallForm();
callForm.setVisible(true);
}
});

}

}

最後,再額外補充兩點:

一,示例程式和真正的CALL外掛開發雖然原理上一樣,工作量卻是天差地別的,時間不充裕者請不要輕易嘗試--|||

二,這個示例僅僅演示了localos的一部分功能,比如dll注入的介面在其中也提供了, 有興趣者可以嘗試一下,但要注意許可權問題.

程式原始碼及示例下載地址:[url]http://code.google.com/p/greenvm/downloads/list[/url] (暫時先丟這裡,原始碼在jar內)

OD下載地址:[url]http://download.csdn.net/source/940795[/url]

PS:由於本例中有些敏感API的呼叫,執行時殺軟對Javaw.exe報警請不要少見多怪...下個版本爭取幹掉殺軟^^
本文出自 “Java究竟怎麼玩” 部落格,請務必保留此出處http://cping1982.blog.51cto.com/601635/125588

相關文章