728x90

# node 다운로드

https://nodejs.org/download/release/latest-v20.x/node-v20.11.1-win-x64.zip

 

# C:\dev 폴더생성

 

# node 

C:\dev\node-v20.11.1-win-x64 에 압축풀기

 

# yarn 설치

C:\dev\node-v20.11.1-win-x64\npm install yarn --global

아래 에러 발생시

C:\dev\Veltrix_React_v5.1.0\Admin>C:\dev\node-v20.11.1-win-x64\yarn install
yarn install v1.22.21
[1/4] Resolving packages...
warning Lockfile has incorrect entry for "moment@^2.29.4". Ignoring it.
error Error: certificate has expired
    at TLSSocket.onConnectSecure (node:_tls_wrap:1674:34)
    at TLSSocket.emit (node:events:518:28)
    at TLSSocket._finishInit (node:_tls_wrap:1085:8)
    at ssl.onhandshakedone (node:_tls_wrap:871:12)
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.

 

ssl/tls 인증서가 만료 https 경고 해제 후 다시 설치

npm config set strict-ssl false
npm install -save react-scripts
npm install -g react-scripts

npm install yarn --global

 

ssl/tls 인증서가 만료 https 경고 해제 후 다시 설치

yarn config set strict-ssl false

 

# React 테마 Veltrix_React_v5.1.0 (유료)

구매한 테마가 있어서 그냥 사용. 다른 테마 사용 등 선택사항

https://themeforest.net/item/veltrix-react-js-admin-dashboard-template/32471505

 

Veltrix - React Js Admin & Dashboard Template

Veltrix is a fully featured premium admin dashboard template built in React Redux Saga with firebase / fake-backend authentication and multi-language supports with developer-friendly code...

themeforest.net

React 테마 Veltrix_React_v5.1.0 아래경로에 복사

C:\dev\Veltrix_React_v5.1.0

 

#React install

CMD로 cd C:\dev\Veltrix_React_v5.1.0\Admin 이동

C:\dev\Veltrix_React_v5.1.0\Admin>C:\dev\node-v20.11.1-win-x64\yarn install

 

#React start

C:\dev\Veltrix_React_v5.1.0\Admin>C:\dev\node-v20.11.1-win-x64\yarn start

 

#http://localhost:3000/

 

리액스 테마 샘플구동 까지 작성...

계속 업데이트 예정...

 

#vscode 설치

https://code.visualstudio.com/Download

 

Download Visual Studio Code - Mac, Linux, Windows

Visual Studio Code is free and available on your favorite platform - Linux, macOS, and Windows. Download Visual Studio Code to experience a redefined code editor, optimized for building and debugging modern web and cloud applications.

code.visualstudio.com

설치파일이아닌 zip파일로 받음 (선택사항)

 

압축을 풀어준뒤 실행하면 된다.

 

 

#vscode spring-boot 플러그인 설치

Extension Pack for Java

Spring Boot extension pack

Lombok Annotations Support for VS Code

 

#자바 17버전 다운로드 및 설정

https://jdk.java.net/archive/

 

Archived OpenJDK GA Releases

Archived OpenJDK General-Availability Releases This page is an archive of previously released builds of the JDK licensed under the GNU General Public License, version 2, with Classpath Exception. WARNING: These older versions of the JDK are provided to he

jdk.java.net

 

#자바 HOME 설정

file > Preferences > Settings

 

java:home > Edit in settings.json

 

 

#Spring Boot 프로젝트 생성

[Ctrl] + [Shift] + [P]

Spring Initializr  엔터

 

 

#vscode 테마변경

Ctrl + K, T

 

#vscode node 터미널 새창에서 실행이 아닌 기본창에서 실행 설정

 

#vscode 패키지 구조가 아닌 폴더구조로 보기 

(단축키: Ctrl + ,) Compact Folders 검색 >  Explorer: Compact Folders 해제

 

#vscode 폴더 아이콘 표시

 

파일 아이콘 테마 설정 

폴더별 아이콘이 직관적으로 표시 된다.

 

#rest api 호출을 위한 Thunder Client 설치 (postMan 대신)

 

#Database manager

#Open in browser (alt + b)

728x90
728x90

Json String to VO

 

@RequestMapping(value="/smp/grd/gridSample02Save.do")
    public @ResponseBody String gridsave(@RequestParam String list, HttpServletRequest request ) throws Exception{        
		
		////////////////////////////////
		//Json형태 String to List<VO>
		////////////////////////////////
		Map<String, List<GridVO>> map = new ObjectMapper().readValue(list, new TypeReference<Map<String, List<GridVO>>>(){});
		
		List<GridVO> updateList = map.get("updateList");
		List<GridVO> addList = map.get("addList");
		List<GridVO> deleteList = map.get("deleteList");
		
		for(GridVO gridVO : updateList){
			System.out.println(gridVO.getBoardName());
		}

		for(GridVO gridVO : addList){
			System.out.println(gridVO.getBoardName());
		}

		for(GridVO gridVO : deleteList){
			System.out.println(gridVO.getBoardName());
		}
		
		////////////////////////////////
		//Json형태 String to List<Map> 
		////////////////////////////////
		Map<String, List<Map>> map01 = new ObjectMapper().readValue(list, new TypeReference<Map<String, List<Map>>>(){});

		List<Map> updateList01 = map01.get("updateList");
		List<Map> addList01 = map01.get("addList");
		List<Map> deleteList01 = map01.get("deleteList");
		
		for(Map mapData : updateList01){
			System.out.println(mapData.get("boardName"));
		}

		for(Map mapData : addList01){
			System.out.println(mapData.get("boardName"));
		}

		for(Map mapData : deleteList01){
			System.out.println(mapData.get("boardName"));
		}
		
        return list;
    }
728x90
728x90

이클립스 화면설계 플러그인

 

https://wireframesketcher.com/download.html

 

Download WireframeSketcher - WireframeSketcher

Try WireframeSketcher for free before you buy it. The software is fully functional for 14 days. After the evaluation period is over, you’ll need a license key in order to save your work. System requirements 64-Bit Operating System: Windows 7, Windows 8,

wireframesketcher.com

 

728x90

'Programming > JAVA' 카테고리의 다른 글

Json String to VO  (0) 2023.04.01
WEB 크롤링 - Selenium  (0) 2023.03.29
WIN10 ipconfig wsl ip tunneling  (0) 2023.03.29
Windows에서 JNA를 사용하여 Java에서 메모리를 조작하는 방법  (0) 2023.03.29
728x90

파이썬 간단한 파일 공유

공유할 폴더로 이동후에

 

python3 -m http.server 8000

 

서버아이피:8000으로 접속하면 파일목록이 보인다.

 

728x90
728x90

Selenium

 

 

이번 프로젝트에서 기존 사이트의 게시판 글을 모두 마이그레이션 해달라는 요청있었다.

처음에는 DB로 데이터를 받을 수있는지 협의해봤는데 DB는 줄수 없다고 답변을 받았다.

그래서 크롤링으로 모두 마이그레이션 하려고 Selenium을 이용하였다.

 

Selenium은 실제 브라우저랑 연동이되어 크롤링 하지 못하는게 없는 강력한 소프트웨어이다.

 

C#, Ruby, Java, Python, JavaScript를 지원한다.

 

난 여기서 내가 쉽게 할 수 있는 Java를 택했다.

 

소스를 코딩한뒤에 실행하면 설정한 브라우저(크롬)이 하나 실행되고 그 브라우저를 바탕으로 크롤링이 된다.

해당 소스를 코딩뒤에 마이그레이션을 빌미로 잘 놀았던것 같다. ^^

 

아래는 내가 구현한 소스이며 더 디테이하게 구현가능하나 간단하게 필요한 부분만 끌거오게 구현하고 프로그램을 돌렸다. 

일회성이라 특별한 기능은 없다.

package board;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;

import org.dataloader.Try;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.openqa.selenium.By;
import org.openqa.selenium.Pdf;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.print.PrintOptions;
import org.openqa.selenium.remote.RemoteWebDriver;

import board.service.MyBatisService;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.nio.file.Paths;

import io.opentelemetry.exporter.logging.SystemOutLogRecordExporter;

public class SeleniumTest {

    public static void main(String[] args) {

    	try {

    		MyBatisService service = new MyBatisService();
    		List<Map<String,Object>> list = service.select();
    		for (Map<String,Object> dept : list) {
    			System.out.println(dept);
    		}



        SeleniumTest selTest = new SeleniumTest();
        //selTest.crawl();
        selTest.crawl2();

    	} catch (Exception e) {
			e.printStackTrace();
		}
    }


    //WebDriver
    private WebDriver driver;

    //Properties
    public static final String WEB_DRIVER_ID = "webdriver.chrome.driver";
    public static final String WEB_DRIVER_PATH = "D:\\mig\\chromedriver_win32\\chromedriver.exe";

    //크롤링 할 URL
    private String base_url;

    public SeleniumTest() {
        super();

        //System Property SetUp
        System.setProperty(WEB_DRIVER_ID, WEB_DRIVER_PATH);

        //Driver SetUp
        ChromeOptions options = new ChromeOptions();
        //options.addArguments("headless");
        //driver = new ChromeDriver();

        //options.setHeadless(true);


        driver = new ChromeDriver(options);
        //base_url = "https://www.naver.com";
        //base_url = "https://www.ppomppu.co.kr/zboard/zboard.php?id=ppomppu";
        base_url = "크롤링할 기본 url";


    }

    public void crawl2() throws IOException {

        try {
            //get page (= 브라우저에서 url을 주소창에 넣은 후 request 한 것과 같다)
            driver.get(base_url);
            try {Thread.sleep(30000);} catch (InterruptedException e) {}


            driver.get("file:///C:/Users/ksmro/Desktop/img.html");

            List<WebElement> els =  driver.findElements(By.xpath("/html/body/a"));


            int i = 0;
            for(WebElement el : els) {
            	System.out.println(i++);
            	el.click();






            	try {Thread.sleep(1000);} catch (InterruptedException e) {}
            }



        }catch (Exception e) {
			e.printStackTrace();
		}

    }

    public void crawl() throws IOException {

    	InputStream in = null;
		OutputStream  out = null;

        try {
            //get page (= 브라우저에서 url을 주소창에 넣은 후 request 한 것과 같다)
            driver.get(base_url);
            try {Thread.sleep(10000);} catch (InterruptedException e) {}



        	int start = 1;
        	int end = 1;
        	String gubun = "구분";
        	String category = "카테고리";
        	String url = "크로링할 URL";

        	Map<String,Object> paramMap = new HashMap<String, Object>();


        	for(int i=start ; i <= end; i++) {
        		driver.get(url + i);
        		//String xpath = "//*[@id=\"53f2b5ad-c15f-482c-8380-75591d206874-a81109f3-bc61-4a8e-8f78-4074ed88811d\"]/tbody/tr";
                //List<WebElement> els = driver.findElements(By.xpath(listXpath));
        		List<WebElement> els = driver.findElements(By.className("ms-itmhover"));


                System.out.println(els.size());

                //List<WebElement> els = driver.findElements(By.xpath("//*[@id=\"d5a214f5-f73f-403a-b4af-f17a8da580c4-0a2feff5-66d5-4555-8fac-935a012105de\"]/tbody/tr"));


                ArrayList<Map<String,Object>> urlList = new ArrayList<Map<String,Object>>();

                if(els.size() == 0) {
                	break;
                }

                var mainImgIdx = 0;

                for(WebElement el : els) {

                	System.out.println(el.getAttribute("innerHTML"));

                	Map<String,Object> map = new HashMap<String, Object>();


                	//WebElement elImg= el.findElement(By.xpath("//span[@class = 'img_box ui-data-thumbnail']"));
                	//String main_img = elImg.findElement(By.tagName("img")).getAttribute("src");

                	//String main_img = el.findElements(By.tagName("img")).get(el.findElements(By.tagName("img")).size()-2).getAttribute("src");
                	String main_img = null;
                	//String main_img = el.findElement(By.xpath("/td/table/tbody/tr/td[2]/div/div["+(++i)+"]/span/img")).getAttribute("src");
                	//String main_img = el.findElement(By.className("img_thumbnail")).findElement(By.tagName("img")).getAttribute("src");


                	//category = null;
                	//try{
                	//	category = el.findElements(By.className("ms-vb2")).get(1).getText();
                	//}catch (Exception e) {
					//	e.printStackTrace();
					//}

                	//news
                	//String link = el.findElement(By.tagName("a")).getAttribute("href");
                	//code
                	String link = null;
                	try{
                		link = el.findElement(By.className("ui-anchor")).getAttribute("href");
                	}catch (Exception e) {
                		e.printStackTrace();
					}



                	System.out.println("link : " + link);

                	if(link != null) {
                		System.out.println(link);
                		//urlList.add(link);
                		map.put("main_img", main_img);
                		map.put("link", link);
                		map.put("category", category);
                		urlList.add(map);
                	}


                	//driver.get(link);
                	//WebElement title = driver.findElement(By.xpath("//*[@id=\"part1\"]/div[3]/div[1]/div/p"));
                	//System.out.println(title);
                	//WebElement body = driver.findElement(By.xpath("//*[@id=\"part1\"]/div[3]/div[2]/div[1]/div/div"));
                	//System.out.println(body);
                }

                for(Map<String,Object> urlMap : urlList) {

                	String urlStr = (String)urlMap.get("link");
                	String main_img = (String)urlMap.get("main_img");
                	//String category = (String)urlMap.get("category");

                	//if("".equals(category)) {
                	//	continue;
                	//}

                	//String uuid = urlStr.replace(idXpath, "");
                	String uuid = null;
                	System.out.println("id : " + uuid);

                	driver.get(urlStr);
                	WebElement webElementTitle = driver.findElement(By.xpath("//*[@id=\"part1\"]/div[3]/div[1]/div/p"));
                	String title = webElementTitle.getText();
                	System.out.println("제목 : " + title);

                	//WebElement webElementBody = driver.findElement(By.xpath("//*[@id=\"part1\"]/div[3]/div[2]/div[1]/div/div"));
                	WebElement webElementBody = null;
                	String body = null;

                	try {
                		webElementBody = driver.findElement(By.xpath("//*[@id=\"part1\"]/div[3]/div[2]/div[1]/div/div/div"));
                		body = webElementBody.getAttribute("innerHTML");
                	}catch (Exception e) {
                		e.printStackTrace();
                		body = "";
                	}

                	//String body = webElementBody.getAttribute("innerHTML");
                	System.out.println("내용 : " + body);

                	WebElement webElementCreateDate = driver.findElement(By.xpath("//*[@id=\"part1\"]/div[3]/div[1]/div/ul/li[2]/span"));
                	String create_date = webElementCreateDate.getText();
                	System.out.println("작성일 : " + create_date);


                	WebElement webElementUser = driver.findElement(By.xpath("//*[@id=\"ctl00_PlaceHolderMain_UFAuthor_Iink_Userlink\"]"));
                	String user_nm = webElementUser.getText();
                	String user_id = webElementUser.getAttribute("href").replace("javascript:fnUserInfo('", "").replace("');", "");
                	System.out.println("작성자 : " + user_nm);
                	System.out.println("user_id : " + user_id);


                	//Document doc = Jsoup.parse(body.getAttribute("innerHTML"));
                	//System.out.println(doc.html());


                	//image down

                	paramMap.put("uuid", uuid);
                	paramMap.put("title", title);
                	paramMap.put("user_id", user_id);
                	paramMap.put("user_nm", user_nm);
                	paramMap.put("create_date", create_date);
                	paramMap.put("body", body);
                	paramMap.put("main_img", main_img);
                	paramMap.put("category", category);

                	paramMap.put("gubun", gubun);

                	MyBatisService service = new MyBatisService();

                	System.out.println("paramMap : " + paramMap);
            		service.insertTmpBoard(paramMap);



                	//*[@id="{DC565DD2-0037-496B-87F2-0A3BA50535D0}"]
                	//*[@id="idAttachmentsTable"]/tbody//a
                	List<WebElement> files = driver.findElements(By.xpath("//*[@id=\"idAttachmentsTable\"]/tbody//a"));
                	for(WebElement file : files) {
                		String fileUrl = file.getAttribute("href");
                		String fileNm = file.getText();
                		System.out.println("file_url : " + fileUrl);
                		System.out.println("file_name : " + fileNm);
                		paramMap.put("file_url", fileUrl);
                		paramMap.put("file_nm", fileNm);

                		service.insertTmpFile(paramMap);
                	}

                	//*[@id="part1"]/div[3]/div[2]/div[1]/div/div/div/img
                	//List<WebElement> imgs = driver.findElements(By.xpath("//*[@id=\"part1\"]/div[3]/div[2]/div[1]/div/div/div/table/tbody/tr[2]//img"));
                	List<WebElement> imgs = driver.findElements(By.xpath("//*[@id=\"part1\"]/div[3]/div[2]/div[1]/div/div/div//img"));

                	for(WebElement img : imgs) {

                		String imgUrl = img.getAttribute("src");

                		System.out.println("imgUrl : " + imgUrl);

                		paramMap.put("img_url", imgUrl);
                		service.insertTmpImg(paramMap);

                		//driver.get(imgUrl);

                		 //URL urlImage = new URL(img.getAttribute("src"));
        				//String fileName = Paths.get(urlImage.getPath()).getFileName().toString();

        				//BufferedImage saveImage = ImageIO.read(urlImage);

                        //download image to the workspace where the project is, save picture as picture.png (can be changed)
        				//ImageIO.write(saveImage, "jpg", new File("D:/mig/img/"+ fileName + ".jpg"));




        				//String USER = users.get(i).replace(".", "_");

        				//File dir = new File("D:/mig/img/" + id);
        				//if ( !dir.exists() ) {
        				//	dir.mkdir();
        				//}
                        //
        				//in = urlImage.openStream();
        				//out = new FileOutputStream("D:/mig/img/" + id + "/" + fileName); //저장경로
                        //
        	            //while(true){
        	            //    //이미지를 읽어온다.
        	            //    int data = in.read();
        	            //    if(data == -1){
        	            //        break;
        	            //    }
        	            //    //이미지를 쓴다.
        	            //    out.write(data);
                        //
        	            //}
                        //
        	            //in.close();
        	            //out.close();

        			}

                }
        	}


        } catch (Exception e) {

            e.printStackTrace();

        } finally {

        	 if(in != null){in.close();}
             if(out != null){out.close();}
        }

    }

}

chromedriver_win32.zip
6.78MB
selenium.z01
17.00MB
selenium.zip
10.09MB

728x90
728x90

안드로이드 폰에 Nextcloud 설치

 

사용하지 않는 폰이 있는데 어떻게 활용할까 찾던 중 안드로이드 폰에 Nextcloud가 설치가 가능하다는 것을 찾았다.

Nextcloud란 개인 파일이나 사진 이메일을 사용할 수 있는 어플리케이션이다.

Clone code using MGit (optional, you can also just use the terminal)
Set "root storage location for repos" to something like /storage/emulated/0
Clone with: Remote URL https://github.com/nextcloud/server.git, Local Path nextcloud (doesn’t support 2FA – if you use that get an app token and log in with that)
Clone the 3rdparty submodule too, local path nextcloud/3rdparty
Install (and optionally clone as well) with Termux
First install some dependencies pkg install php php-fpm sqlite coreutils openssl-tool
Allow Termux to access storage outside of own folder termux-setup-storage
(If you want to clone with Termux: cd /storage/emulated/0/ && git clone https://github.com/nextcloud/server.git nextcloud)
Get the Nextcloud submodules cd /storage/emulated/0/nextcloud/ && git submodule update --init
Start the server php -S 0.0.0.0:8080 -t /storage/emulated/0/nextcloud/
Finish setup in Firefox
Go to http://0.0.0.0:8080
Set an admin username and password in the
(SQLite will be used as database)

실제로 가이드대로 안쓰는 구글픽셀 원에 실행해보니 정상적으로 사용이 가능했다.

오래전에 설치해봐서 현재 설치 사진은 없다.

 

https://github.com/jancborchardt/nextcloud-scripts/blob/master/nextcloud-on-android.md

 

GitHub - jancborchardt/nextcloud-scripts: ☁️ Scripts to easier set up & update Nextcloud

☁️ Scripts to easier set up & update Nextcloud. Contribute to jancborchardt/nextcloud-scripts development by creating an account on GitHub.

github.com

 

728x90
728x90

WIN10 ipconfig wsl ip

윈도우 wsl ubuntu 아이피가 바겼을때 확인하고 터널링 실행

package com.gaon.client.main;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gaon.client.thread.FileThread;


public class ServiceMain {

	private static final Logger log = LoggerFactory.getLogger(ServiceMain.class);

	public static void main(String[] args) {
		
		try {
		
			//System.out.println("test");
			//TextReadToDbService service = new TextReadToDbService();
			//service.textReadToDb();
			//System.out.println("end");
			
			
			//파일삭제
			//Thread t = new Thread(new FileThread(), "Thread-01");
			//t.start();
			
			execute("wsl -t Ubuntu 2", 0);
			execute("ipconfig", 1);
			


			
		} catch (Exception e) {
			log.warn(ExceptionUtils.getStackTrace(e));
		}

	}
	
	public static void execute(String cmd, int gb) throws Exception{
		
		Thread.sleep(5000);
		
        Process process = null;
        Runtime runtime = Runtime.getRuntime();
        StringBuffer successOutput = new StringBuffer(); // 성공 스트링 버퍼
        StringBuffer errorOutput = new StringBuffer(); // 오류 스트링 버퍼
        BufferedReader successBufferReader = null; // 성공 버퍼
        BufferedReader errorBufferReader = null; // 오류 버퍼
        String msg = null; // 메시지
 
        List<String> cmdList = new ArrayList<String>();
 
        // 운영체제 구분 (window, window 가 아니면 무조건 linux 로 판단)
        if (System.getProperty("os.name").indexOf("Windows") > -1) {
            cmdList.add("cmd");
            cmdList.add("/c");
        } else {
            cmdList.add("/bin/sh");
            cmdList.add("-c");
        }
        // 명령어 셋팅
        cmdList.add(cmd);
        String[] array = cmdList.toArray(new String[cmdList.size()]);
 
        try {
 
            // 명령어 실행
            process = runtime.exec(array);
 
            // shell 실행이 정상 동작했을 경우
            successBufferReader = new BufferedReader(new InputStreamReader(process.getInputStream(), "EUC-KR"));
 
            while ((msg = successBufferReader.readLine()) != null) {
                successOutput.append(msg + System.getProperty("line.separator"));
            }
 
            // shell 실행시 에러가 발생했을 경우
            errorBufferReader = new BufferedReader(new InputStreamReader(process.getErrorStream(), "EUC-KR"));
            while ((msg = errorBufferReader.readLine()) != null) {
                errorOutput.append(msg + System.getProperty("line.separator"));
            }
 
            // 프로세스의 수행이 끝날때까지 대기
            process.waitFor();
 
            // shell 실행이 정상 종료되었을 경우
            if (process.exitValue() == 0) {
            	log.warn("성공");
            	log.warn(successOutput.toString());
            } else {
                // shell 실행이 비정상 종료되었을 경우
            	log.warn("비정상 종료");
            	log.warn(successOutput.toString());
            }
 
            
            if(gb == 1) {
            	settingIp(successOutput.toString());
            	
            }
            
            
            log.warn("errorOutput" + errorOutput.toString());
            
            // shell 실행시 에러가 발생
            //if (CommonUtil.notEmpty(errorOutput.toString())) {
                // shell 실행이 비정상 종료되었을 경우
            //    System.out.println("오류");
            //    System.out.println(successOutput.toString());
           // }
 
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            try {
                process.destroy();
                if (successBufferReader != null) successBufferReader.close();
                if (errorBufferReader != null) errorBufferReader.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
    }

	public static void settingIp(String out) {
		
		BufferedReader reader = null; 
		String ip = "";
		
		try {
			
			reader = new BufferedReader(new StringReader(out));
			
		    String line = null;
	        int idx = 0;
	        int ipIdx = 0;
	        
	        while ((line = reader.readLine()) != null  ) {
	        	++idx;
	        	log.warn(line);
	        	if(line.equals("이더넷 어댑터 vEthernet (WSL):")) {
	        		ipIdx = idx;
	        	}
	        	if(ipIdx != 0 && idx == (ipIdx + 4)) {
	        		log.warn("ip : " + line.replace("   IPv4 주소 . . . . . . . . . : ", ""));
	        		ip = line.replace("   IPv4 주소 . . . . . . . . . : ", "");
	        	}
	        }
	        
	        String cmd = "wsl -d ubuntu -u root autossh -f -M 13000 -N -i /home/ksm/key/oracleCloudOpenssh.ppk ubuntu@ksmcloud.duckdns.org -p 22 -o 'StrictHostKeyChecking=no' -o 'ExitOnForwardFailure=yes' -o 'ServerAliveInterval 30' -o 'ServerAliveCountMax 3' -R 32400:#{ip}:32400"; 
	        cmd = cmd.replace("#{ip}", ip);
	        log.warn("cmd : " + cmd);
	        
	        execute(cmd, 0);
	        
	        
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		} finally {
			if(reader != null) {
				try {
					reader.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}

        
	}

}
728x90
728x90

자바에서 특정 윈도우 응용프로그램의 메모리 값을 읽어오는 방법이 궁금해서 구글링을 해보니 해당 예제가 나와서 메모 해둠.

언젠가는 쓸일이 있을 것 같으므로 ...

 

https://stackoverflow.com/questions/18849609/how-to-manipulate-memory-from-java-with-jna-on-windows

 

How to manipulate memory from Java with JNA on Windows

How do I manipulate memory from Java? I know that Java runs in it's own JVM, so it can't access process memory directly. I heard about JNA which can be used to get interfaces between the Operating

stackoverflow.com

 

아래내용은 해당 링크의 번역 입니다.

 

JNA 라이브러리를 사용해야 합니다. 두 개의 Jar 파일(jna.jar 및 jna-platform.jar)을 다운로드합니다 .

이 라이브러리를 사용하는 방법을 설명하는 pastebin에 대한 자습서를 찾았습니다 . 그러나 다음을 이해하기 위해 읽을 필요는 없습니다.

Windows 게임 "Solitaire"의 주소와 해당 값을 조작하려고 한다고 가정해 보겠습니다.


알고, 당신이 무엇을

  1. 주소와 해당 값을 조작하려는 경우 수행할 작업을 알고 있어야 합니다!
    주소에 저장된 값의 크기를 알아야 합니다. 4Byte인지, 8Byte인지 등등.
  2. 도구를 사용하여 동적 및 기본 주소를 얻는 방법을 알아두십시오. 나는 CheatEngine을 사용합니다 .
  3. 기본 주소와 동적 주소의 차이점을 알아두세요.
    • 동적 주소는 애플리케이션(솔리테어)을 다시 시작할 때마다 변경됩니다.
      여기에는 필요한 값이 포함되지만 매번 주소를 다시 찾아야 합니다. 따라서 먼저 배워야 할 것은 기본 주소를 얻는 방법입니다.
      CheatEngine Tutorial을 통해 플레이하면서 이를 배우십시오.
    • 기본 주소는 정적 주소입니다. 이러한 주소는 주로 다음과 같은 방식으로 다른 주소를 가리킵니다. [[base-adres + offset] + offset] -> value. 따라서 필요한 것은 기본 주소와 동적 주소를 얻기 위해 주소에 추가해야 하는 오프셋을 아는 것입니다.

이제 알아야 할 사항을 알았으므로 Solitaire에서 CheatEngine으로 몇 가지 조사를 수행합니다.


동적 주소를 찾았고 기본 주소를 검색했습니까? 좋습니다. 결과를 공유해 보겠습니다.

점수에 대한 기본 주소: 0x10002AFA8
동적 주소에 도달하기 위한 오프셋: 0x50(첫 번째) 및 0x14(두 번째)

모든 것이 맞습니까? 좋은! 계속해서 실제로 코드를 작성해 보겠습니다.


새 프로젝트 만들기

새 프로젝트에서 해당 라이브러리를 가져와야 합니다. Eclipse를 사용하지만 다른 IDE에서도 작동해야 합니다.

User32 인터페이스

User32 인터페이스를 설정해 준 Todd Fast에게 감사드립니다 . 완전하지는 않지만 여기에 필요한 것은 충분합니다.

이 인터페이스를 사용하여 Windows에서 user32.dll의 일부 기능에 액세스할 수 있습니다. 다음 기능이 필요합니다 FindWindowA.GetWindowThreadProcessID

참고: Eclipse에서 구현되지 않은 메서드를 추가해야 한다고 표시되면 무시하고 코드를 실행하십시오.

Kernel32 인터페이스

Kernel32 인터페이스 에 대해 Deject3d에게 감사드립니다 . 조금 수정했습니다.

이 인터페이스에는 메모리를 읽고 쓰는 데 사용하는 메서드가 포함되어 있습니다. WriteProcessMemory그리고 ReadProcessMemory. 프로세스를 여는 방법도 포함되어 있습니다.OpenProcess

실제 조작

이제 몇 가지 도우미 메서드와 JVM의 액세스 지점으로 기본 기능을 포함할 새 클래스를 만듭니다.

public class SolitaireHack {

    public static void main(String... args)
    {

    }
}

오프셋 및 기본 주소와 같이 이미 알고 있는 항목을 입력해 보겠습니다.

public class SolitaireHack {

    final static long baseAddress = 0x10002AFA8L;
    final static int[] offsets = new int[]{0x50,0x14};

    public static void main(String... args)
    {

    }
}

다음으로 인터페이스를 사용하여 Windows 특정 메서드에 액세스합니다.

import com.sun.jna.Native;

public class SolitaireHack {

    final static long baseAddress = 0x10002AFA8L;
    final static int[] offsets = new int[]{0x50,0x14};

    static Kernel32 kernel32 = (Kernel32) Native.loadLibrary("kernel32",Kernel32.class);
    static User32 user32 = (User32) Native.loadLibrary("user32", User32.class);

    public static void main(String... args)
    {

    }
}

마지막으로 프로세스에 대한 읽기 및 쓰기 권한을 얻기 위해 필요한 몇 가지 권한 상수를 만듭니다.

import com.sun.jna.Native;

public class SolitaireHack {

    final static long baseAddress = 0x10002AFA8L;
    final static int[] offsets = new int[]{0x50,0x14};

    static Kernel32 kernel32 = (Kernel32) Native.loadLibrary("kernel32",Kernel32.class);
    static User32 user32 = (User32) Native.loadLibrary("user32", User32.class);

    public static int PROCESS_VM_READ= 0x0010;
    public static int PROCESS_VM_WRITE = 0x0020;
    public static int PROCESS_VM_OPERATION = 0x0008;

    public static void main(String... args)
    {

    }
}

메모리를 조작할 수 있는 프로세스를 얻으려면 창을 가져와야 합니다. 이 창을 사용하여 프로세스 ID를 얻을 수 있습니다 . 이 ID로 프로세스를 열 수 있습니다.

public static void main(String... args)
{
    int pid = getProcessId("Solitaire");
    Pointer process = openProcess(PROCESS_VM_READ|PROCESS_VM_WRITE|PROCESS_VM_OPERATION, pid);
}

public static int getProcessId(String window) {
     IntByReference pid = new IntByReference(0);
     user32.GetWindowThreadProcessId(user32.FindWindowA(null, window), pid);

     return pid.getValue();
}

public static Pointer openProcess(int permissions, int pid) {
     Pointer process = kernel32.OpenProcess(permissions, true, pid);
     return process;
}

메서드 에서 getProcessId우리는 창의 제목인 매개변수를 사용하여 창 핸들을 찾습니다. ( FindWindowA) 이 창 핸들은 프로세스 ID를 가져오는 데 사용됩니다. IntByReference는 프로세스 ID가 저장되는 포인터의 JNA 버전입니다.

프로세스 ID를 얻으면 이를 사용하여 openProcess. 이 메서드는 프로세스를 열기 위한 권한과 pid를 가져오고 프로세스에 대한 포인터를 반환합니다. 프로세스에서 읽으려면 PROCESS_VM_READ 권한이 필요하고 프로세스에서 쓰려면 PROCESS_VM_WRITE 및 PROCESS_VM_OPERATION 권한이 필요합니다.

다음으로 가져와야 할 것은 실제 주소입니다. 동적 주소입니다. 따라서 다른 방법이 필요합니다.

public static void main(String... args)
{
    int pid = getProcessId("Solitaire");
    Pointer process = openProcess(PROCESS_VM_READ|PROCESS_VM_WRITE|PROCESS_VM_OPERATION, pid);

    long dynAddress = findDynAddress(process,offsets,baseAddress);
}

public static long findDynAddress(Pointer process, int[] offsets, long baseAddress)
{

    long pointer = baseAddress;

    int size = 4;
    Memory pTemp = new Memory(size);
    long pointerAddress = 0;

    for(int i = 0; i < offsets.length; i++)
    {
        if(i == 0)
        {
             kernel32.ReadProcessMemory(process, pointer, pTemp, size, null);
        }

        pointerAddress = ((pTemp.getInt(0)+offsets[i]));

        if(i != offsets.length-1)
             kernel32.ReadProcessMemory(process, pointerAddress, pTemp, size, null);


    }

    return pointerAddress;
}

이 방법에는 프로세스, 오프셋 및 기본 주소가 필요합니다. 객체 에 일부 임시 데이터를 저장합니다 Memory. 이것이 정확히 말하는 것입니다. 기억. 기본 주소에서 읽고 메모리에 새 주소를 가져와 오프셋을 추가합니다. 이것은 모든 오프셋에 대해 수행되며 결국 동적 주소가 될 마지막 주소를 반환합니다.

이제 점수를 읽고 출력하려고 합니다. 우리는 점수가 저장된 동적 주소를 가지고 있고 그것을 읽어야 합니다. 점수는 4Byte 값입니다. 정수는 4바이트 데이터 유형입니다. 따라서 Integer를 사용하여 읽을 수 있습니다.

public static void main(String... args)
{
    int pid = getProcessId("Solitaire");
    Pointer process = openProcess(PROCESS_VM_READ|PROCESS_VM_WRITE|PROCESS_VM_OPERATION, pid);

    long dynAddress = findDynAddress(process,offsets,baseAddress);

    Memory scoreMem = readMemory(process,dynAddress,4);
    int score = scoreMem.getInt(0);
    System.out.println(score);
}

public static Memory readMemory(Pointer process, long address, int bytesToRead) {
    IntByReference read = new IntByReference(0);
    Memory output = new Memory(bytesToRead);

    kernel32.ReadProcessMemory(process, address, output, bytesToRead, read);
    return output;
}

우리는 kernel32 메서드에 대한 래퍼를 작성했습니다 readProcessMemory. 우리는 4Byte를 읽어야 한다는 것을 알고 있으므로 bytesToRead는 4가 됩니다. 메서드에서 개체 Memory가 생성되고 반환되며 크기는 byteToRead이고 주소에 포함된 데이터를 저장합니다. 메서드 를 사용하면 .getInt(0)오프셋 0에서 메모리의 정수 값을 읽을 수 있습니다.

솔리테어로 약간 플레이하고 점수를 얻으십시오. 그런 다음 코드를 실행하고 값을 읽습니다. 그것이 당신의 점수인지 확인하십시오.

마지막 단계는 점수를 조작하는 것입니다. 우리는 최고가 되고 싶습니다. 따라서 메모리에 4Byte 데이터를 써야 합니다.

byte[] newScore = new byte[]{0x22,0x22,0x22,0x22};

이것은 우리의 새로운 점수가 될 것입니다. newScore[0]가장 낮은 바이트가 되고 newScore[3]가장 높은 바이트가 됩니다. 따라서 점수를 값 20으로 변경하려면 다음과 byte[]같이 하십시오.
byte[] newScore = new byte[]{0x14,0x00,0x00,0x00};

메모리에 적어 봅시다.

public static void main(String... args)
{
    int pid = getProcessId("Solitaire");
    Pointer process = openProcess(PROCESS_VM_READ|PROCESS_VM_WRITE|PROCESS_VM_OPERATION, pid);

    long dynAddress = findDynAddress(process,offsets,baseAddress);

    Memory scoreMem = readMemory(process,dynAddress,4);
    int score = scoreMem.getInt(0);
    System.out.println(score);

    byte[] newScore = new byte[]{0x22,0x22,0x22,0x22};
    writeMemory(process, dynAddress, newScore);
}

public static void writeMemory(Pointer process, long address, byte[] data)
{
    int size = data.length;
    Memory toWrite = new Memory(size);

    for(int i = 0; i < size; i++)
    {
            toWrite.setByte(i, data[i]);
    }

    boolean b = kernel32.WriteProcessMemory(process, address, toWrite, size, null);
}

우리의 방법을 사용하면 호출된 데이터를 주소에 writeMemory씁니다 . byte[]새 객체를 생성 Memory하고 크기를 배열의 길이로 설정합니다. 올바른 오프셋으로 개체 에 데이터를 쓰고 Memory주소에 개체를 씁니다.

이제 572662306의 환상적인 점수를 얻었을 것입니다.

정확히 모르는 경우 일부 kernel32 또는 user32 메서드가 수행하는 작업은 MSDN을 참조하거나 자유롭게 문의하십시오.

알려진 문제:

Solitaire의 프로세스 ID를 얻지 못한 경우 작업 관리자에서 확인하고 수동으로 pid를 작성하십시오. 독일 Solitär는 작동하지 않습니다. 이름의 ä 때문인 것 같습니다.

이 튜토리얼이 마음에 드셨기를 바랍니다. 대부분의 부분은 다른 튜토리얼에서 가져온 것이지만 여기에 모두 정리되어 있으므로 누군가 시작점이 필요한 경우 도움이 될 것입니다.

Deject3d와 Todd Fast의 도움에 다시 한 번 감사드립니다. 문제가 있는 경우 저에게 말씀해 주시면 도와드리겠습니다. 빠진 것이 있으면 언제든지 알려 주시거나 직접 추가해 주세요.

감사합니다. 좋은 하루 되세요.


SolitaireHack 클래스의 전체 코드를 살펴보겠습니다.

import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;

public class SolitaireHack {

    final static long baseAddress = 0x10002AFA8L;
    final static int[] offsets = new int[]{0x50,0x14};

    static Kernel32 kernel32 = (Kernel32) Native.loadLibrary("kernel32",Kernel32.class);
    static User32 user32 = (User32) Native.loadLibrary("user32", User32.class);

    public static int PROCESS_VM_READ= 0x0010;
    public static int PROCESS_VM_WRITE = 0x0020;
    public static int PROCESS_VM_OPERATION = 0x0008;

    public static void main(String... args)
    {
        int pid = getProcessId("Solitaire");
        Pointer process = openProcess(PROCESS_VM_READ|PROCESS_VM_WRITE|PROCESS_VM_OPERATION, pid);

        long dynAddress = findDynAddress(process,offsets,baseAddress);

        Memory scoreMem = readMemory(process,dynAddress,4);
        int score = scoreMem.getInt(0);
        System.out.println(score);

        byte[] newScore = new byte[]{0x22,0x22,0x22,0x22};
        writeMemory(process, dynAddress, newScore);
    }

    public static int getProcessId(String window) {
         IntByReference pid = new IntByReference(0);
         user32.GetWindowThreadProcessId(user32.FindWindowA(null, window), pid);

         return pid.getValue();
    }

    public static Pointer openProcess(int permissions, int pid) {
         Pointer process = kernel32.OpenProcess(permissions, true, pid);
         return process;
    }

    public static long findDynAddress(Pointer process, int[] offsets, long baseAddress)
    {

        long pointer = baseAddress;

        int size = 4;
        Memory pTemp = new Memory(size);
        long pointerAddress = 0;

        for(int i = 0; i < offsets.length; i++)
        {
            if(i == 0)
            {
                 kernel32.ReadProcessMemory(process, pointer, pTemp, size, null);
            }

            pointerAddress = ((pTemp.getInt(0)+offsets[i]));

            if(i != offsets.length-1)
                 kernel32.ReadProcessMemory(process, pointerAddress, pTemp, size, null);


        }

        return pointerAddress;
    }

    public static Memory readMemory(Pointer process, long address, int bytesToRead) {
        IntByReference read = new IntByReference(0);
        Memory output = new Memory(bytesToRead);

        kernel32.ReadProcessMemory(process, address, output, bytesToRead, read);
        return output;
    }

    public static void writeMemory(Pointer process, long address, byte[] data)
    {
        int size = data.length;
        Memory toWrite = new Memory(size);

        for(int i = 0; i < size; i++)
        {
                toWrite.setByte(i, data[i]);
        }

        boolean b = kernel32.WriteProcessMemory(process, address, toWrite, size, null);
    }
}

 

해당게시글의 링크의 내용

이 라이브러리를 사용하는 방법을 설명하는 pastebin에 대한 자습서를

 

this topic assumes that:1) you are semi proficient at game hacking/memory edit - Pastebin.com

Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.

pastebin.com

this topic assumes that:
1) you are semi proficient at game hacking/memory editing/programming
2) you've already downloaded the JNA.jar and related files and know how to set it up.

I haven't found a solid example/explanation of how to do this, so i'll try my best;

warning: this is not purely java by any means. as far as I know, java can't interact with anything in the OS as it runs in a virtual machine. i have no idea how the hell this JNA thing works, but oh well.

In this example, you will be learning how to cheat at the game "3d pinball" that comes with windows by using  JNA.jar to interface with the native windows functions for editing memory.

Now, I'm pretty clueless as to how the JNA actually works, and I pieced this together myself from pretty much nothing. It's still mostly magic to me, but I'll give you everything you need to get at least an example working.

First of all, you need an interface for each native windows function you want to use. Here's my code for Kernel32.dll. It is far from complete, but plenty for this example. Kernel32 contains the necessary crap for memory editing. I hope you knew that.

[code]
import com.sun.jna.*;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.ptr.IntByReference;

// by deject3d 

public interface Kernel32 extends StdCallLibrary
{
    // description from msdn
    //BOOL WINAPI WriteProcessMemory(
    //__in   HANDLE hProcess,
    //__in   LPVOID lpBaseAddress,
    //__in   LPCVOID lpBuffer,
    //__in   SIZE_T nSize,
    //__out  SIZE_T *lpNumberOfBytesWritten
    //);
    boolean WriteProcessMemory(Pointer p, int address, Pointer buffer, int size, IntByReference written);
    
    
    //BOOL WINAPI ReadProcessMemory(
    //          __in   HANDLE hProcess,
    //          __in   LPCVOID lpBaseAddress,
    //          __out  LPVOID lpBuffer,
    //          __in   SIZE_T nSize,
    //          __out  SIZE_T *lpNumberOfBytesRead
    //        );
    boolean ReadProcessMemory(Pointer hProcess, int inBaseAddress, Pointer outputBuffer, int nSize, IntByReference outNumberOfBytesRead);
    
    
    //HANDLE WINAPI OpenProcess(
    //  __in  DWORD dwDesiredAccess,
    //  __in  BOOL bInheritHandle,
    //  __in  DWORD dwProcessId
    //);
    Pointer OpenProcess(int desired, boolean inherit, int pid);
    
    /* derp */
    int GetLastError();
}
[/code]


User32 also contains a few very important functions - GetWindowThreadProcessID and FindWindowA. Here's some code I luckily lifted off of google. I think it's the entire User32 class rewritten as java. Thanks, Mr. Todd Fast. now, this is way more than we need, but it could be nice to have someday.

[code]
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.examples.win32.W32API;
import com.sun.jna.examples.win32.GDI32.RECT;
import com.sun.jna.ptr.ByteByReference;
import com.sun.jna.ptr.IntByReference;

/** Provides access to the w32 user32 library.
 * Incomplete implementation to support demos.
 *  
 * @author  Todd Fast, todd.fast@sun.com
 * @author twall@users.sf.net
 */
public interface User32 extends W32API {

    User32 INSTANCE = (User32)
        Native.loadLibrary("user32", User32.class, DEFAULT_OPTIONS);
    
    Pointer GetDC(Pointer hWnd);
    int ReleaseDC(Pointer hWnd, Pointer hDC);

    int FLASHW_STOP = 0;
    int FLASHW_CAPTION = 1;
    int FLASHW_TRAY = 2;
    int FLASHW_ALL = (FLASHW_CAPTION|FLASHW_TRAY);
    int FLASHW_TIMER = 4;
    int FLASHW_TIMERNOFG = 12;
    
    public static class FLASHWINFO extends Structure {
        public int cbSize;
        public Pointer hWnd;
        public int dwFlags;
        public int uCount;
        public int dwTimeout;
    }

    int IMAGE_BITMAP=0;
    int IMAGE_ICON=1;
    int IMAGE_CURSOR=2;
    int IMAGE_ENHMETAFILE=3;

    int LR_DEFAULTCOLOR     =0x0000;
    int LR_MONOCHROME       =0x0001;
    int LR_COLOR            =0x0002;
    int LR_COPYRETURNORG    =0x0004;
    int LR_COPYDELETEORG    =0x0008;
    int LR_LOADFROMFILE     =0x0010;
    int LR_LOADTRANSPARENT  =0x0020;
    int LR_DEFAULTSIZE      =0x0040;
    int LR_VGACOLOR         =0x0080;
    int LR_LOADMAP3DCOLORS  =0x1000;
    int LR_CREATEDIBSECTION =0x2000;
    int LR_COPYFROMRESOURCE =0x4000;
    int LR_SHARED           =0x8000;

    Pointer FindWindowA(String winClass, String title);
    int GetClassName(Pointer hWnd, byte[] lpClassName, int nMaxCount);
    public static class GUITHREADINFO extends Structure {
        public int cbSize = size();
        public int flags;
        Pointer hwndActive;
        Pointer hwndFocus;
        Pointer hwndCapture;
        Pointer hwndMenuOwner;
        Pointer hwndMoveSize;
        Pointer hwndCaret;
        RECT rcCaret;
    }
    boolean GetGUIThreadInfo(int idThread, GUITHREADINFO lpgui);
    
    public static class WINDOWINFO extends Structure {
        public int cbSize = size();
        public RECT rcWindow;
        public RECT rcClient;
        public int dwStyle;
        public int dwExStyle;
        public int dwWindowStatus;
        public int cxWindowBorders;
        public int cyWindowBorders;
        public short atomWindowType;
        public short wCreatorVersion;
    }
    boolean GetWindowInfo(Pointer hWnd, WINDOWINFO pwi);
    boolean GetWindowRect(Pointer hWnd, RECT rect);
    int GetWindowText(Pointer hWnd, byte[] lpString, int nMaxCount);
    int GetWindowTextLength(Pointer hWnd);
    int GetWindowModuleFileName(Pointer hWnd, byte[] lpszFileName, int cchFileNameMax);
    int GetWindowThreadProcessId(Pointer hWnd, IntByReference lpdwProcessId);
    interface WNDENUMPROC extends StdCallCallback {
        /** Return whether to continue enumeration. */
        boolean callback(Pointer hWnd, Pointer data);
    }
    boolean EnumWindows(WNDENUMPROC lpEnumFunc, Pointer data);
    boolean EnumThreadWindows(int dwThreadId, WNDENUMPROC lpEnumFunc, Pointer data);

    boolean FlashWindowEx(FLASHWINFO info);

    Pointer LoadIcon(Pointer hInstance, String iconName);

    Pointer LoadImage(Pointer hinst,   // handle to instance 
                      String name,  // image to load 
                      int type,        // image type 
                      int xDesired,     // desired width 
                      int yDesired,     // desired height 
                      int load        // load options 
    );

    boolean DestroyIcon(Pointer hicon);

    int GWL_EXSTYLE = -20;
    int GWL_STYLE = -16;
    int GWL_WNDPROC = -4;
    int GWL_HINSTANCE = -6;
    int GWL_ID = -12;
    int GWL_USERDATA = -21;
    int DWL_DLGPROC = 4;
    int DWL_MSGRESULT = 0;
    int DWL_USER = 8;
    int WS_EX_COMPOSITED = 0x20000000;
    int WS_EX_LAYERED = 0x80000;
    int WS_EX_TRANSPARENT = 32;
    int GetWindowLong(Pointer hWnd, int nIndex);
    int SetWindowLong(Pointer hWnd, int nIndex, int dwNewLong);

    int LWA_COLORKEY = 1;
    int LWA_ALPHA = 2;
    int ULW_COLORKEY = 1;
    int ULW_ALPHA = 2;
    int ULW_OPAQUE = 4;
    boolean SetLayeredWindowAttributes(Pointer hwnd, int crKey, 
                                       byte bAlpha, int dwFlags);
    boolean GetLayeredWindowAttributes(Pointer hwnd,
                                       IntByReference pcrKey,
                                       ByteByReference pbAlpha,
                                       IntByReference pdwFlags);

    /** Defines the x- and y-coordinates of a point. */
    public static class POINT extends Structure {
        public int x, y;
    }
    /** Specifies the width and height of a rectangle. */
    public static class SIZE extends Structure {
        public int cx, cy;
    }
    int AC_SRC_OVER = 0x00;
    int AC_SRC_ALPHA = 0x01;
    int AC_SRC_NO_PREMULT_ALPHA = 0x01;
    int AC_SRC_NO_ALPHA = 0x02;
    public static class BLENDFUNCTION extends Structure {
        public byte BlendOp = AC_SRC_OVER; // only valid value
        public byte BlendFlags = 0; // only valid value
        public byte SourceConstantAlpha;
        public byte AlphaFormat;
    }
    boolean UpdateLayeredWindow(Pointer hwnd, Pointer hdcDst, 
                                POINT pptDst, SIZE psize, 
                                Pointer hdcSrc, POINT pptSrc, int crKey, 
                                BLENDFUNCTION pblend, int dwFlags);
    int SetWindowRgn(Pointer hWnd, Pointer hRgn, boolean bRedraw);
    int VK_SHIFT = 16;
    int VK_LSHIFT = 0xA0;
    int VK_RSHIFT = 0xA1;
    int VK_CONTROL = 17;
    int VK_LCONTROL = 0xA2;
    int VK_RCONTROL = 0xA3;
    int VK_MENU = 18;
    int VK_LMENU = 0xA4;
    int VK_RMENU = 0xA5;
    boolean GetKeyboardState(byte[] state);
    short GetAsyncKeyState(int vKey);
}
[/code]

Good. copy and paste both of those into your java project.

Now, make the class that will be containing the actual code for cheating. I named my class Cheater.

[code]
public class Cheater
{
    public static void main(String[] args)
    {

    }
}
[/code]

Amazing. now what?

First, imports. lots of them.

[code]
import java.util.Arrays;
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.*;

public class Cheater
{
    public static void main(String[] args)
    {

    }
}
[/code]

Okay, cool. we've got imports. Can we start memory editing yet? no. not even close. you now need to load the native libraries using the JNA.

here's how.

[code]
import java.util.Arrays;
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.*;

public class Cheater
{
    static Kernel32 kernel32 = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
    static User32     user32 = (User32)   Native.loadLibrary("user32"  , User32.class);
    
    public static void main(String[] args)
    {

        }
}
[/code]

cool spacing, eh? yeah, whatever. you should be focusing.

So, now that we have the interface's to the native functions all set up, we can start hackin', right?! still not close.

Pretend you're memory editing in C++ or visual basic or whatever else - what do you need to do first before you can read/write memory to a process? you need the process ID. so how the hell do we get the process ID? just like in C++ - we use GetWindowThreadProcessId() !

so, GetWindowThreadProcessID() is located in user32.dll - so let's peek at our interface.

[code]
...
     int GetWindowThreadProcessId(Pointer hWnd, IntByReference lpdwProcessId);
...
[/code]

great, the function is in our interface. that means we can use it. but... how do we do that? what the hell is a Pointer in java terms? how do we get the hWnd?! IntByReference?! wtf?!

yeah, this is why this is hard to do. we're basically translating C++ into java.

anyways, the first parameter for GetWindowThreadProcessId() is a hWnd. how do we get that in C++? with FindWindowA() of course!

let's see now... yep, FindWindowA() is definitely in our user32 interface-

[code]
     Pointer FindWindowA(String winClass, String title);
[/code]

luckily, it takes Strings (phew). us java users know how those work (i hope).

so let's piece together some code, shall we?

why not make a getProcessId() method in our cheater class just to make things easier to read and use.

[code]
    public static int getProcessId(String window)
    {
        IntByReference pid = new IntByReference(0);
        user32.GetWindowThreadProcessId(user32.FindWindowA(null,window), pid);
        
        return pid.getValue();
    }
[/code]

perfect. this will return the integer process ID of the window we ask for - but as you can probably tell, I skipped ahead of myself a bit.

the first thing you notice is 

[code]
IntByReference pid = new IntByReference(0);
[/code]

an IntByReference comes from our import "import com.sun.jna.ptr.IntByReference;" It is just used as a pointer, basically. the variable "pid" is where GetWindowThreadProcessId will put the processes PID. we can't use just regular java ints because of what the MSDN documentation says:


[code]

DWORD WINAPI GetWindowThreadProcessId(
  __in       HWND hWnd,
  __out_opt  LPDWORD lpdwProcessId
);
[/code]
[url]http://msdn.microsoft.com/en-us/library/ms633522(VS.85).aspx[/url]
"LPDWORD
- A pointer to a variable that receives the process identifier."

since it has to be a pointer, we're forced to use IntByReference. You should be able to figure out how they work just by looking at the code above.

"pid.getValue()" just turns the pointer back into a regular java int. easy enough.

-------------------------

Alright, great. We can now get the process ID of a given process. here's how it should look:

[code]
import java.util.Arrays;
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.*;

public class Cheater
{
    static Kernel32 kernel32 = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
    static User32     user32 = (User32)   Native.loadLibrary("user32"  , User32.class);
    
    public static void main(String[] args)
    {
        int pid = getProcessId("3D Pinball for Windows - Space Cadet");
    }
    
    public static int getProcessId(String window)
    {
        IntByReference pid = new IntByReference(0);
        user32.GetWindowThreadProcessId(user32.FindWindowA(null,window), pid);
        
        return pid.getValue();
    }
[/code]

great, we're getting somewhere. But what comes next? if this were C++, we would need to open the process so that we can start getting down and dirty. that's right, now we get to rewrite OpenProcess().

let's check it out in the Kernel32 interface;

[code]
    /*
    HANDLE WINAPI OpenProcess(
      __in  DWORD dwDesiredAccess,
      __in  BOOL bInheritHandle,
      __in  DWORD dwProcessId
    );
     */
    Pointer OpenProcess(int desiredAccess, boolean inherit, int pid);
[/code]

this should be relatively straightforward to any experienced people - the MSDN documentation ([url]http://msdn.microsoft.com/en-us/library/ms684320(VS.85).aspx[/url]) tells us the parameters.

so, it takes a DWORD (also known as double word (which is also known as int. 4 bytes. i'm sure you knew that.)) to know what access we're trying to open the process with. check out some of the possible values here- [url]http://msdn.microsoft.com/en-us/library/ms684880(v=VS.85).aspx[/url]

then we can see that it takes a boolean. the boolean isn't so important. we like it when it is true.

finally, it takes in the processID. we got that earlier! yay!

so let's write another method in our Cheater class to, once again, make things easier on ourself.

[code]
    public static Pointer openProcess(int permissions, int pid)
    {
        Pointer process = kernel32.OpenProcess(permissions,true, pid);
        return process;
    }
[/code]

that was simple enough. the most difficult part of getting all of this to work is re-coding the C++ datatypes as java datatypes. I don't even remember how I figured out how it should return a Pointer. luckily for us, it gets even more difficult later. (since java has no unsigned data types)

so let's see how things are shaping up so far;

[code]
import java.util.Arrays;
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.*;

public class Cheater
{
    static Kernel32 kernel32 = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
    static User32     user32 = (User32)   Native.loadLibrary("user32"  , User32.class);
    
    public static void main(String[] args)
    {
        int pid = getProcessId("3D Pinball for Windows - Space Cadet");
        Pointer readprocess = openProcess(0x0010, pid);
    }
    
    public static int getProcessId(String window)
    {
        IntByReference pid = new IntByReference(0);
        user32.GetWindowThreadProcessId(user32.FindWindowA(null,window), pid);
        
        return pid.getValue();
    }
    
    public static Pointer openProcess(int permissions, int pid)
    {
        Pointer process = kernel32.OpenProcess(permissions,true, pid);
        return process;
    }
[/code]

if you're confused as to why "Pointer readprocess = openProcess(0x0010, pid);" has 0x0010, go back to this link: [url]http://msdn.microsoft.com/en-us/library/ms684880(v=VS.85).aspx[/url]

[quote]
PROCESS_VM_READ (0x0010)	Required to read memory in a process using ReadProcessMemory.
[/quote]

right-o.

so now let's have some fun. let's make java print out our current score!

for that, we now need to recreate ReadProcessMemory(). I gave you the interface for it in the Kernel32 class:

[code]
    /*
    BOOL WINAPI ReadProcessMemory(
              __in   HANDLE hProcess,
              __in   LPCVOID lpBaseAddress,
              __out  LPVOID lpBuffer,
              __in   SIZE_T nSize,
              __out  SIZE_T *lpNumberOfBytesRead
            );
    */
    boolean ReadProcessMemory(Pointer hProcess, int inBaseAddress, Pointer outputBuffer, int nSize, IntByReference outNumberOfBytesRead);
[/code]

so let's go through those paremeters.

Pointer hProcess - check (our variable "readprocess")

int inBaseAddress - check (the memory address we want to start reading from. if you need help with this step, check out some tutorials on finding memory addresses using a memory searcher/editor such as Memory Hacking Software ([url]http://memoryhacking.com/)[/url])

Pointer outbutBuffer - ok, what the hell is this? let's check the trusty MSDN:

[quote]
lpBuffer [out]
A pointer to a buffer that receives the contents from the address space of the specified process.
[/quote]

so basically, it's where the memory that we read is going to be stored. i'll show you how this works in a second.

int nSize - this is just how much memory we should be reading from the process (in bytes) remember, an integer value is 4 bytes. most of the time you're going to be reading 4 bytes if you want to read a number.

IntByReference outNumberOfBytesRead - the MSDN tells us that this will hold the number of bytes that actually gets read. it will be the same as nSize most of the time.

-------

alright, so let's piece this this together by making another method in our Cheater class.

[code]
    public static Memory readMemory(Pointer process, int address, int bytesToRead)
    {
        IntByReference read = new IntByReference(0);
        Memory output = new Memory(bytesToRead);
        
        kernel32.ReadProcessMemory(process, address, output, bytesToRead, read);
        return output;
    }
[/code]

let's break this down:

we know what an IntByReference is for, but what is a "Memory" ? Memory is just a class that the JNA uses to hold memory. go figure. the constructor it takes is how much memory it should hold (in bytes)

hopefully the rest is fully understandable. if not, feel free to ask about it.


so this is how the Cheater class should look so far:

[code]
import java.util.Arrays;
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.*;

public class Cheater
{
    static Kernel32 kernel32 = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
    static User32     user32 = (User32)   Native.loadLibrary("user32"  , User32.class);
    
    public static void main(String[] args)
    {
        int pid = getProcessId("3D Pinball for Windows - Space Cadet");
        Pointer readprocess = openProcess(0x0010, pid);
        int size = 4;
        Memory read = readMemory(readprocess,0x00AB0C62,size);
    }

    public static int getProcessId(String window)
    {
        IntByReference pid = new IntByReference(0);
        user32.GetWindowThreadProcessId(user32.FindWindowA(null,window), pid);
        
        return pid.getValue();
    }
    
    public static Pointer openProcess(int permissions, int pid)
    {
        Pointer process = kernel32.OpenProcess(permissions,true, pid);
        return process;
    }

    public static Memory readMemory(Pointer process, int address, int bytesToRead)
    {
        IntByReference read = new IntByReference(0);
        Memory output = new Memory(bytesToRead);
        
        kernel32.ReadProcessMemory(process, address, output, bytesToRead, read);
        return output;
    }
}
[/code]

"int size = 4;"
this is the size in bytes of what we want to read. since the score is held in an integer and an integer is 4 bytes, we definitely want to read 4 bytes.

"Memory read = readMemory(readprocess,0x00AB0C62,size);"
0x00AB0C62 is the memory address that holds the score for pinball.

now you see that we're using the Memory class again to hold.. well, memory.

so how do we get the value out of the Memory class? simple. we read 4 bytes. 4 bytes is an integer. the Memory class has a method for this.

read.getInt(0) (0 is the offset. we don't want an offset)

so.. great. now we can read memory with java!

let's see how it all comes together.

[code]
import java.util.Arrays;
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.*;

public class Cheater
{
    static Kernel32 kernel32 = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
    static User32     user32 = (User32)   Native.loadLibrary("user32"  , User32.class);
    
    public static void main(String[] args)
    {
        int pid = getProcessId("3D Pinball for Windows - Space Cadet"); // get our process ID
        Pointer readprocess = openProcess(0x0010, pid); // open the process ID with read priviledges.
        
        int size = 4; // we want to read 4 bytes
        Memory read = readMemory(readprocess,0x00AB0C62,size); // read 4 bytes of memory starting at the address 0x00AB0C62.

        System.out.println(read.getInt(0)); // print out the value!
    }
    
    public static int getProcessId(String window)
    {
        IntByReference pid = new IntByReference(0);
        user32.GetWindowThreadProcessId(user32.FindWindowA(null,window), pid);
        
        return pid.getValue();
    }
    
    public static Pointer openProcess(int permissions, int pid)
    {
        Pointer process = kernel32.OpenProcess(permissions,true, pid);
        return process;
    }
    
    public static Memory readMemory(Pointer process, int address, int bytesToRead)
    {
        IntByReference read = new IntByReference(0);
        Memory output = new Memory(bytesToRead);
        
        kernel32.ReadProcessMemory(process, address, output, bytesToRead, read);
        return output;
    }
}
[/code]

congratulations, you now have the framework for reading process memory with java.

i'm not going to jerk your chain around and make you guess on how to write memory with java. it's pretty much the same process:

[code]
    public static int writeMemory(Pointer process, int address, short[] data)
    {
        IntByReference written =  new IntByReference(0);
        
        Memory toWrite = new Memory(data.length);
        
        for(long i = 0; i < data.length;i++)
        {
            toWrite.setShort(0, data[new Integer(Long.toString(i))]);
        }
        
        boolean b = kernel32.WriteProcessMemory(process, address, toWrite, data.length, written);
        return written.getValue();
    }
[/code]


Enjoy!

- Deject3d

User32 인터페이스를

 

User32 Interface - Pastebin.com

Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.

pastebin.com

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.WinDef.RECT;
import com.sun.jna.ptr.ByteByReference;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.win32.StdCallLibrary.StdCallCallback;
import com.sun.jna.win32.W32APIOptions;

public interface User32 extends W32APIOptions {  
    User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class, DEFAULT_OPTIONS);  
    Pointer GetDC(Pointer hWnd);  
    int ReleaseDC(Pointer hWnd, Pointer hDC);  
    int FLASHW_STOP = 0;  
    int FLASHW_CAPTION = 1;  
    int FLASHW_TRAY = 2;  
    int FLASHW_ALL = (FLASHW_CAPTION | FLASHW_TRAY);  
    int FLASHW_TIMER = 4;  
    int FLASHW_TIMERNOFG = 12;  
    public static class FLASHWINFO extends Structure {  
        public int cbSize;  
        public Pointer hWnd;  
        public int dwFlags;  
        public int uCount;  
        public int dwTimeout;  
    }  
    int IMAGE_BITMAP = 0;  
    int IMAGE_ICON = 1;  
    int IMAGE_CURSOR = 2;  
    int IMAGE_ENHMETAFILE = 3;  
    int LR_DEFAULTCOLOR = 0x0000;  
    int LR_MONOCHROME = 0x0001;  
    int LR_COLOR = 0x0002;  
    int LR_COPYRETURNORG = 0x0004;  
    int LR_COPYDELETEORG = 0x0008;  
    int LR_LOADFROMFILE = 0x0010;  
    int LR_LOADTRANSPARENT = 0x0020;  
    int LR_DEFAULTSIZE = 0x0040;  
    int LR_VGACOLOR = 0x0080;  
    int LR_LOADMAP3DCOLORS = 0x1000;  
    int LR_CREATEDIBSECTION = 0x2000;  
    int LR_COPYFROMRESOURCE = 0x4000;  
    int LR_SHARED = 0x8000;  
    Pointer FindWindowA(String winClass, String title);  
    int GetClassName(Pointer hWnd, byte[] lpClassName, int nMaxCount);  
    public static class GUITHREADINFO extends Structure {  
        public int cbSize = size();  
        public int flags;  
        Pointer hwndActive;  
        Pointer hwndFocus;  
        Pointer hwndCapture;  
        Pointer hwndMenuOwner;  
        Pointer hwndMoveSize;  
        Pointer hwndCaret;  
        RECT rcCaret;  
    }  
    boolean GetGUIThreadInfo(int idThread, GUITHREADINFO lpgui);  
    public static class WINDOWINFO extends Structure {  
        public int cbSize = size();  
        public RECT rcWindow;  
        public RECT rcClient;  
        public int dwStyle;  
        public int dwExStyle;  
        public int dwWindowStatus;  
        public int cxWindowBorders;  
        public int cyWindowBorders;  
        public short atomWindowType;  
        public short wCreatorVersion;  
    }  
    boolean GetWindowInfo(Pointer hWnd, WINDOWINFO pwi);  
    boolean GetWindowRect(Pointer hWnd, RECT rect);  
    int GetWindowText(Pointer hWnd, byte[] lpString, int nMaxCount);  
    int GetWindowTextLength(Pointer hWnd);  
    int GetWindowModuleFileName(Pointer hWnd, byte[] lpszFileName, int cchFileNameMax);  
    int GetWindowThreadProcessId(Pointer hWnd, IntByReference lpdwProcessId);  
    interface WNDENUMPROC extends StdCallCallback {  
        /**
         * Return whether to continue enumeration.
         */  
        boolean callback(Pointer hWnd, Pointer data);  
    }  
    boolean EnumWindows(WNDENUMPROC lpEnumFunc, Pointer data);  
    boolean EnumThreadWindows(int dwThreadId, WNDENUMPROC lpEnumFunc, Pointer data);  
    boolean FlashWindowEx(FLASHWINFO info);  
    Pointer LoadIcon(Pointer hInstance, String iconName);  
    Pointer LoadImage(Pointer hinst, // handle to instance  
            String name, // image to load  
            int type, // image type  
            int xDesired, // desired width  
            int yDesired, // desired height  
            int load // load options  
            );  
    boolean DestroyIcon(Pointer hicon);  
    int GWL_EXSTYLE = -20;  
    int GWL_STYLE = -16;  
    int GWL_WNDPROC = -4;  
    int GWL_HINSTANCE = -6;  
    int GWL_ID = -12;  
    int GWL_USERDATA = -21;  
    int DWL_DLGPROC = 4;  
    int DWL_MSGRESULT = 0;  
    int DWL_USER = 8;  
    int WS_EX_COMPOSITED = 0x20000000;  
    int WS_EX_LAYERED = 0x80000;  
    int WS_EX_TRANSPARENT = 32;  
    int GetWindowLong(Pointer hWnd, int nIndex);  
    int SetWindowLong(Pointer hWnd, int nIndex, int dwNewLong);  
    int LWA_COLORKEY = 1;  
    int LWA_ALPHA = 2;  
    int ULW_COLORKEY = 1;  
    int ULW_ALPHA = 2;  
    int ULW_OPAQUE = 4;  
    boolean SetLayeredWindowAttributes(Pointer hwnd, int crKey,  
            byte bAlpha, int dwFlags);  
    boolean GetLayeredWindowAttributes(Pointer hwnd,  
            IntByReference pcrKey,  
            ByteByReference pbAlpha,  
            IntByReference pdwFlags);  
    /**
     * Defines the x- and y-coordinates of a point.
     */  
    public static class POINT extends Structure {  
        public int x, y;  
    }  
    /**
     * Specifies the width and height of a rectangle.
     */  
    public static class SIZE extends Structure {  
        public int cx, cy;  
    }  
    int AC_SRC_OVER = 0x00;  
    int AC_SRC_ALPHA = 0x01;  
    int AC_SRC_NO_PREMULT_ALPHA = 0x01;  
    int AC_SRC_NO_ALPHA = 0x02;  
    public static class BLENDFUNCTION extends Structure {  
        public byte BlendOp = AC_SRC_OVER; // only valid value  
        public byte BlendFlags = 0; // only valid value  
        public byte SourceConstantAlpha;  
        public byte AlphaFormat;  
    }  
    boolean UpdateLayeredWindow(Pointer hwnd, Pointer hdcDst,  
            POINT pptDst, SIZE psize,  
            Pointer hdcSrc, POINT pptSrc, int crKey,  
            BLENDFUNCTION pblend, int dwFlags);  
    int SetWindowRgn(Pointer hWnd, Pointer hRgn, boolean bRedraw);  
    int VK_SHIFT = 16;  
    int VK_LSHIFT = 0xA0;  
    int VK_RSHIFT = 0xA1;  
    int VK_CONTROL = 17;  
    int VK_LCONTROL = 0xA2;  
    int VK_RCONTROL = 0xA3;  
    int VK_MENU = 18;  
    int VK_LMENU = 0xA4;  
    int VK_RMENU = 0xA5;  
    boolean GetKeyboardState(byte[] state);  
    short GetAsyncKeyState(int vKey);  
}

ernel32 인터페이스

 

Kernel32 Interface - Pastebin.com

Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.

pastebin.com

import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.win32.StdCallLibrary;

public interface Kernel32 extends StdCallLibrary  
{  
    // description from msdn  
    //BOOL WINAPI WriteProcessMemory(  
    //__in   HANDLE hProcess,  
    //__in   LPVOID lpBaseAddress,  
    //__in   LPCVOID lpBuffer,  
    //__in   SIZE_T nSize,  
    //__out  SIZE_T *lpNumberOfBytesWritten  
    //);  
    boolean WriteProcessMemory(Pointer p, long address, Pointer buffer, int size, IntByReference written);  
     
     
    //BOOL WINAPI ReadProcessMemory(  
    //          __in   HANDLE hProcess,  
    //          __in   LPCVOID lpBaseAddress,  
    //          __out  LPVOID lpBuffer,  
    //          __in   SIZE_T nSize,  
    //          __out  SIZE_T *lpNumberOfBytesRead  
    //        );  
    boolean ReadProcessMemory(Pointer hProcess, long inBaseAddress, Pointer outputBuffer, int nSize, IntByReference outNumberOfBytesRead);  
     
     
    //HANDLE WINAPI OpenProcess(  
    //  __in  DWORD dwDesiredAccess,  
    //  __in  BOOL bInheritHandle,  
    //  __in  DWORD dwProcessId  
    //);  
    Pointer OpenProcess(int desired, boolean inherit, int pid);  
     
    /* derp */  
    int GetLastError();  
}

https://drive.google.com/file/d/1GLxYKfl6gG53cNyVwLpTlMTdIPjY2-NH/view?usp=share_link 

 

Google Drive: 로그인

이메일 또는 휴대전화

accounts.google.com

 

728x90

'Programming > JAVA' 카테고리의 다른 글

Json String to VO  (0) 2023.04.01
이클립스 화면설계 플러그인  (0) 2023.04.01
WEB 크롤링 - Selenium  (0) 2023.03.29
WIN10 ipconfig wsl ip tunneling  (0) 2023.03.29

+ Recent posts