由於原文較長,圖又比較多,且CSDN博客圖片目前無法外部訪問|||,所以僅發來部分,全文請去鄙人CSDN的博客:[url]http://blog.csdn.net/cping1982[/url] ,希望51cto能早日提供博客遷移功能……
示例運行結果如下圖:
/**
* 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:[email][email protected][/email]
* @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報警請不要少見多怪...下個版本爭取幹掉殺軟^^