package org.tzd.frida;

import org.tzd.frida.windows.CallbackMessage;
import org.tzd.frida.windows.Frida;
import org.tzd.frida.windows.FridaRunnable;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * Main 类用于启动和执行 Frida 注入操作。
 *
 * <p>此类主要包含一个入口方法 <code>main</code>，用于加载必要的本地库并初始化 Frida 对象。</p>
 * <p>它会通过调用 <code>getProcessPid</code> 方法获取指定进程的 PID，并将 JavaScript 代码注入到目标进程中。</p>
 *
 * @author tzdwindows 7
 */
public class Main {

    /**
     * 程序入口方法。
     *
     * <p>此方法加载本地 DLL 库并创建一个 <code>Frida</code> 实例。接着通过 <code>run</code> 和 <code>execute</code> 方法执行指定的任务。</p>
     * <p>执行期间，会将回调函数添加到 <code>Frida</code> 实例中，接收并打印消息。</p>
     *
     * @param args 命令行参数
     */
    public static void main(String[] args) {
        // 加载本地 DLL 文件
        System.load("C:\\Users\\Administrator\\source\\repos\\FridaNative\\x64\\Release\\FridaNative.dll");

        // 创建 Frida 实例并传入 JavaScript 代码及进程 PID
        Frida frida = new Frida("console.log('Hello, Frida!');", getProcessPid("java.exe"));

        // 执行 Frida 任务，注入代码并注册回调函数
        frida.run(new Runnable() {
            @Override
            public void run() {
                // 在此处添加要执行的代码
            }
        }).execute(new FridaRunnable() {
            @Override
            public void run(Frida frida) {
                // 注册回调消息，接收到消息时打印
                frida.addCallbackMessage(new CallbackMessage() {
                    @Override
                    public void onMessage(String message) {
                        System.out.println(message); // 打印收到的消息
                    }
                });
            }
        }).start(); // 启动线程
    }

    /**
     * 获取指定进程的 PID。
     *
     * <p>此方法通过运行 Windows 命令 <code>tasklist</code> 获取系统中所有正在运行的进程，并查找指定进程名。</p>
     * <p>一旦找到匹配的进程，它将提取进程的 PID 并返回。</p>
     *
     * @param processName 要查找的进程名称。
     * @return 目标进程的 PID，如果未找到则返回 -1。
     */
     public static long getProcessPid(String processName) {
        long pid = -1;
        try {
            ProcessBuilder builder = new ProcessBuilder("tasklist");
            builder.redirectErrorStream(true);
            Process process = builder.start();
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;

            while ((line = reader.readLine()) != null) {
                if (line.contains(processName)) {
                    String[] parts = line.split("\\s+");
                    pid = Long.parseLong(parts[1]);
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return pid;
    }
}
