'guitest'에 해당되는 글 6건

  1. 2012.10.24 [KPW2012] Notepad Letter (7)
  2. 2008.12.11 플래시 게임을 즐기자. (5)
  3. 2008.12.01 네이트온 쪽지 자동답장 프로그램 (5)
  4. 2008.12.01 한글 문자열을 키보드 자판의 영문자로 변환 (4)
  5. 2008.11.28 Win32::Process::Memory (6)
  6. 2008.11.17 Win32::GuiTest - Perl GUI Test Utilities. (2)

Naver Perl Community & Study Cafe


2012.10.24 03:37

[KPW2012] Notepad Letter

2008년말 쯤에 한글 문자열을 자판에 입력되는 영문으로 바꾸는 방법  이라는 글을 쓴적이 있습니다.

당시에는 별 생각없이 기술연구 목적으로 테스트 용으로 만들었는데...

가끔 이 모듈을 이용해서 응용작품을 만들어 봐야 겠다는 생각을 하곤 했었죠.


최근에는 인문학이나, 감성, Design for humans 등등 

사람 중심의 문화가 많이 생기고 정착되고 있는 시기입니다.


이렇듯 소프트웨어를 통해 사람의 마음을 움직이는 프로그램이 필요하다고 느꼈고, 

향후에는 사람에게 메세지를 전달하는 정성을 넣어 감동으로 연결시키는

인간적인 프로그램이 앞으로는 크게 이슈가 될 것 같더라구요 ㅋㅋ


그런면에서 Notepad Letter은 그런 부분을 충족시켜주는 부분이 많았습니다.


4년만에 다시 열린 Korean Perl Workshop 2012 에서 발표할 기회가 생겨,

이 모듈을 다시 한번 연구해서 살을 붙여보자 하고 결심했습니다.


아래는 KPW2012 발표 자료입니다.

https://docs.google.com/file/d/0B3NurlLan8deZUJ4Yk1jVy1aM3c/edit?pli=1


Hangle.pm

package Hangle; use strict; use warnings; use Lingua::KO::Hangul::Util qw(:all); use base qw/Exporter/; use Encode qw/decode encode/; our @EXPORT_OK = qw/transformation/; sub transformation{ my $arg = shift; my $str = decode('cp-949', $arg); binmode STDOUT, ':encoding(cp-949)'; my %hangle = ( #초성 "\x{1100}" => 'r', "\x{1102}" => 's', "\x{1103}" => 'e', "\x{1105}" => 'f', # ㄱㄴㄷㄹ "\x{1106}" => 'a', "\x{1107}" => 'q', "\x{1109}" => 't', "\x{110B}" => 'd', # ㅁㅂㅅㅇ "\x{110C}" => 'w', "\x{110E}" => 'c', "\x{110F}" => 'z', "\x{1110}" => 'x', # ㅈㅊㅋㅌ "\x{1111}" => 'v', "\x{1112}" => 'g', "\x{1101}" => 'R', "\x{1104}" => 'E', # ㅍㅎㄲ ㄸ "\x{1108}" => 'Q', "\x{110A}" => 'T', "\x{110D}" => 'W', # ㅃ ㅆ ㅉ #중성 "\x{1161}" => 'k', "\x{1163}" => 'i', "\x{1165}" => 'j', "\x{1167}" => 'u', # ㅏㅑㅓㅕ "\x{1169}" => 'h', "\x{116D}" => 'y', "\x{116E}" => 'n', "\x{1172}" => 'b', # ㅗㅛㅜㅠ "\x{1173}" => 'm', "\x{1175}" => 'l', # ㅡㅣ "\x{1162}" => 'o', "\x{1164}" => 'O', "\x{1166}" => 'p', "\x{1168}" => 'P', # ㅐㅒㅔㅖ #종성 "\x{11A8}" => 'r', "\x{11AB}" => 's', "\x{11AE}" => 'e', "\x{11AF}" => 'f', # ㄱㄴㄷㄹ "\x{11B7}" => 'a', "\x{11B8}" => 'q', "\x{11BA}" => 't', "\x{11BC}" => 'd', # ㅁㅂㅅㅇ "\x{11BD}" => 'w', "\x{11BE}" => 'c', "\x{11BF}" => 'z', "\x{11C0}" => 'x', # ㅈㅊㅋㅌ "\x{11C1}" => 'v', "\x{11C2}" => 'g', # ㅍㅎ "\x{11A9}" => 'R', "\x{11BB}" => 'T', # ㄲ ㅆ #특수문자 "\x{20}" => ' ' , "\x{A}" => "\n" , "\x{2E}" => '.' , "\x{2C}" => ',' , #Space Enter . , "\x{2D}" => '-' , #Number "\x{30}" => '0' , "\x{31}" => '1' , "\x{32}" => '2' , "\x{33}" => '3' , "\x{34}" => '4' , "\x{35}" => '5' , "\x{36}" => '6' , "\x{37}" => '7' , "\x{38}" => '8' , "\x{39}" => '9' , ); my @jamos = map { split //, decomposeJamo($_) }split //, decomposeSyllable($str); my $keys = '{HAN}'; foreach (@jamos) { $keys .= $hangle{$_} } # print "$strokes"; return $keys; }



- 아래는 스크립트 입니다. 공개하니 부끄럽네요 ㅡ_ㅠ

use strict;
use warnings;    
use Win32::GuiTest qw(:ALL);
use Win32::MediaPlayer;
use Hangle qw/transformation/;

my $file = 'background.mp3';
my $winmm = new Win32::MediaPlayer;  
$winmm->load($file);        
$winmm->play;                   
$winmm->volume(100);            

# notepad 시작
system("start notepad.exe");
sleep 3;

#전체 창 띄우기 
max_window();

#한글 키 입력
Win32::GuiTest::SendKeys("{HAN}");

#글씨체 및 폰트 바꾸기
font_change("휴먼편지체",36);
sleep 3;

writing("너를 만나기 전까진.");
waiting();
waiting();
newLine();

writing("내 마음은 차가운 겨울처럼 멈춰있는 신호등과 같았어.");
waiting();
waiting();
newLine();

writing("하지만 너를 만나면서 무뚝뚝하던 내가");
newLine(); # Enter 한줄 내리기 
writing("조금씩 웃고 있다는 걸 깨달았지.");
sleep 4;

# 전체 지우기
clear();

writing("때론 설레임으로 잠을 못 이루기도 하고,");
sleep 2;
newLine(); # Enter 한줄 내리기 

writing("너의 웃음소리가 귓가에 맴돌아 나도 모르게 미소 짓고,");
sleep 2;
newLine(); # Enter 한줄 내리기 

writing("데이트하는 날이면, 시계만 종일 쳐다보는 나를 발견했어.");
waiting();
waiting();
newLine(); # Enter 한줄 내리기
newLine(); # Enter 한줄 내리기

writing("그래.");
waiting();
waiting();
waiting();
writing(" 나 지금 설래이고 떨려.");
waiting();
waiting();
sleep 4;

# 전체 지우기
clear();

writing("지금 네 앞의 남자는");
sleep 3;
newLine();
writing("아직 부족하고 모자라지만,");
sleep 3;
newLine();
newLine();

writing("너만을 사랑하고");
sleep 1;
writing(" 너만을 아껴주는");
sleep 1;
writing(" 멋진 남자가 될께.");
sleep 3;

newLine();
newLine();

writing("우리 앞으로 ");
sleep 1;
writing("행복 하게 지내자 ");
Win32::GuiTest::SendKeys("+6+6");
sleep 3;
newLine();
newLine();

writing("그리고.");
waiting();
waiting();
waiting();

writing(" 사");
waiting();
waiting();
waiting();
writing("랑");
sleep 1;

# 빨리 지우기 
backspace(12);


#천천히 지우기 
backspace(1);
sleep 1;
backspace(1);
sleep 1;
backspace(1);
sleep 1;

writing(" 사랑한다");
writing(" 누구누구야");
Win32::GuiTest::SendKeys("!!");
sleep 5;

#notepad 종료하기
end();

#음악 종료
$winmm->pause;

# 동영상 FullScreen으로 재생
system('"C:\Program Files (x86)\Windows Media Player\wmplayer.exe" C:\동영상.wmv /fullscreen');

# 폰트 변경하기
sub font_change {
  my ( $font,$size ) = (@_);
  my $cmd = "%of".transformation($font)."{TAB}{TAB}".$size;
  Win32::GuiTest::SendKeys($cmd);
  sleep 2;
  Win32::GuiTest::SendKeys("~");
  sleep 3;
}

# 최대창으로 변경 
sub max_window{
   Win32::GuiTest::SendKeys("%{SPACE}x");
   sleep 3;
}

# 한글 변환해서 출력 
sub writing{
  my $text = shift;
  Win32::GuiTest::SendKeys(transformation($text));
}

# . 찍으며 1초씩 기다리기
sub waiting{
  Win32::GuiTest::SendKeys(".");
  sleep 1;	
}

# Enter 한줄 내리기
sub newLine{
  Win32::GuiTest::SendKeys("~");  
}

# Ctrl+A 후 Backspace 키로 전체 지우기
sub clear{
  Win32::GuiTest::SendKeys("^a{BACKSPACE}");
}

# Backspace 사용
sub backspace{
   my ($count) = shift;
   Win32::GuiTest::SendKeys("{BACKSPACE}") for(1..$count) ;
}

#NotePad 종료
sub end{
  Win32::GuiTest::SendKeys("%{F4}{TAB}{ENTER}");
}

Link : http://codepad.org/uPhPvpSx



글을 쓸때 참고했던 URL 입니다 (http://whitelove002.tistory.com/290) 

작가님께 감사합니다 ^^;;



4년만에 함께한 Korean Perl workshop 아주 흥미로웠고 재밌었던 주제가 많았습니다.

특히 Web 분야가 상당히 많이 발전하고 있더군요.

배울점도 많고, 좋은 사람도 많이 만났습니다.


@Gypark 님을 드디어 뵙는 역사적인 날이기도 했구요 ㅋㅋ


좋은 행사를 준비해주신 관리자 분들께 감사드리구요!

11월 모임 때 뵙겠습니다^^/


http://event.perl.kr/kpw2012/


아래는 동영상입니다 ㅠ 흑엽님이 올려주셨는데.. 공개해도 될지..


신고
Trackback 2 Comment 7
2008.12.11 17:42

플래시 게임을 즐기자.


홈런랠리라는 플래시게임이 있다.

이 게임은 투수가 공을 던지면 그 공을 받아 치면 되는 게임으로써 


여기에 가면 직접 게임을 해 볼 수 있다.

게임을 하던중 생각했다.

GuiTest를 사용하면 치트키처럼 다 홈런을 칠 수 있지 않을까? +_+

그래서 일정한 간격으로 마우스를 좌로 우로 움직이며 클릭을 해주는 코드를 짠 뒤 테스트를 했다...






젠장.....
신고
Trackback 2 Comment 5
2008.12.01 12:56

네이트온 쪽지 자동답장 프로그램


네이트온 사용시 부재시 자동으로 답장을 해주는 프로그램을 만들어 봤다.. 


네이트온에는 부재시 4종류의 행동패턴만 지원한다. ( 자리비움 , 다른용무중 , 통화중 , 회의중 )

세부적으로 어떤일을 하고 있는지 정확히 알 수 없으므로 

내가 하고 있는일을 전달하기가 어려울 때가 있다.


사람의 마음이라는것이 다 똑같다

쪽지를 한번 씹기 시작하면 인간관계가 서글퍼지므로

넓은 인맥관계를 형성하기 위한...

프로젝트... -_-...


쪽지가 왔을때 즉시 자동으로 답장을 해주며 

부재중이더라도 사람들에게 친절하게 답장할 수 있는 프로그램을 소개한다..


사실 만들고 나서야 알았지만

대규모 쪽지들도 모두 잽싸게 처리를 할 수 있다.

이런 류의 일을 하는 사람한테 도움이 될 수도 있다. 

 

제작 언어 

Perl 후후후...


필요한 모듈

 

- Win32::GuiTest   자동답장을 하기 위한 모듈 

- Lingua::KO::Hangle::Util

   GuiTest는 한글을 지원하지 않기 때문에

   한글을 영문으로 변환하는 모듈이 필요 

- Hangle 모듈 - 이전글에서 만들었던 모듈이다.

  

프로그램 설명

 - 돌아가는 원리는 간단하다.

   프로그램을 실행하면 쪽지에 관련된 창을 찾은 뒤

   쪽지보내기 창으로 전환 후에 부재중 메세지를 남긴 후

   단축키를 통하여 메세지를 보낸다.

   무한루프를 너무 많이 돌리면 시스템이 과부화 될 수있으니

   적당히 2초에 한번씩 쪽지읽기 창을 찾아 메세지를 처리한다.


프로그램


콘솔용이다.


기본 메세지는 "부재중임으로 나중에 연락하겠습니다.." 이런 메세지를 넣어놨고


인자값으로 메세지를 넣으면 그 메세지를 자동으로 전송한다.


GUI 구현 - 미정... ㅡ_ㅡ;

신고
Trackback 0 Comment 5
2008.12.01 00:55

한글 문자열을 키보드 자판의 영문자로 변환


예전 WIn32::GuiTest 모듈을 사용한 예제에서

영문만 지원이 되고 한글은 지원되지 않기에

한글문자열이 직접 영문타자로 변환되는 모듈을 만들어 볼까 생각했었다.


오늘 시간이 남아 일단 여러 자료들을 다 펼쳐놓고 작업에 들어갔는데...


크게 정리하자면

1. 한글 문자열을 각 문자단위로 조각조각 낸다.
2. 조각조각 낸 단위의 문자들을 각각 영문키로 바꾼다.
3. 끝(?)....


응?? 어떻게 보면 간단하다... 

하지만 세부적으로 들어가야하는 코딩은 까다롭기 때문에

잘 생각해보자.


가장먼저 한글을 쪼개어서 각 문자코드로 변환시켜주는 모듈을 소개한다.

Lingua::KO::Hangul::Util

utility functions for Hangul in Unicode 
Lingua-KO-Hangul-Util-0.23 - 05 Jun 2007 - SADAHIRO Tomoyuki 

이 유익한 모듈은... 일본사람이 만들었다.. 쳇...

모듈을 통해 간단한 테스트 코드를 만들어 테스트를 해보았다.

각 모듈을 조각조각 내는것은 어렵지 않게

decomposeSyllable 함수를 쓰면 조각 내어진다.




이 모듈을 가지고 얼마전 a3r0님이 

이름을 서로 매칭시켜 궁합을 보는 프로그램을 만든 적이 있었다.


그래서 이 모듈을 조금만 수정하면 각각의 문자값에 영문자를 넣어

변형할 수 있을 것이란 생각이 들었다.




이 모듈은 decomposeJamo 라는 함수를 제공하는데

이 함수는 ㄲ(&#x1101) 을 ㄱ(&#x1100)ㄱ(&#x1100) 으로 나누어준다.

ㄲ을 자판의 키로 옮길때는 대문자 R이 되어야 하는데...

rr(소문자r2개) 으로 바꿔서 처리하니 변환하기가 곤란했다.

그렇다고 decomposeJamo 함수를 안쓰려니...

종성에서 ㄳ 을 ㄱ 과 ㅅ으로 ㄺ 을 ㄹ 과 ㄱ으로

나누어주는 편리함때문에 이 모듈을 안 쓸 수도 없었다.


진퇴양난...


일단 나만의 함수를 만들기에 아직 실력이 출중하지 않고...

결국 이 모듈을 내가 편하게 고쳐서 사용하기로 하였다.

decomposeJamo 함수를 사용하되

쌍자음과 ㅐ,ㅒ,ㅖ ,ㅔ 같은 모음들은 변환이 안되게 변환되는 부분에서

주석처리를 해버리는 방법이었다.

나중에야 발견했지만

종성에서 ㄲ 과 ㅆ 도 변환되지 않게 처리해야 한다는 것을 알았다.

그래서 이렇게 변환해주는 모듈을 완성을 해보았다.



Hangle.pm

package Hangle;

use strict;
use warnings;
use Lingua::KO::Hangul::Util qw(:all);
use base qw/Exporter/;
use Encode qw/decode encode/;

our @EXPORT_OK = qw/transformation/;

sub transformation{
	my $arg = shift;
	my $str = decode('cp-949', $arg);
	binmode STDOUT, ':encoding(cp-949)';
	my %hangle = (
			#초성
			"\x{1100}" => 'r', "\x{1102}" => 's', "\x{1103}" => 'e', "\x{1105}" => 'f',  # ㄱㄴㄷㄹ
			"\x{1106}" => 'a', "\x{1107}" => 'q', "\x{1109}" => 't', "\x{110B}" => 'd',  # ㅁㅂㅅㅇ
			"\x{110C}" => 'w', "\x{110E}" => 'c', "\x{110F}" => 'z', "\x{1110}" => 'x',  # ㅈㅊㅋㅌ
			"\x{1111}" => 'v', "\x{1112}" => 'g', "\x{1101}" => 'R', "\x{1104}" => 'E',  # ㅍㅎㄲ ㄸ
			"\x{1108}" => 'Q', "\x{110A}" => 'T', "\x{110D}" => 'W',                     # ㅃ ㅆ ㅉ		  
			#중성
			"\x{1161}" => 'k', "\x{1163}" => 'i', "\x{1165}" => 'j', "\x{1167}" => 'u',  # ㅏㅑㅓㅕ
			"\x{1169}" => 'h', "\x{116D}" => 'y', "\x{116E}" => 'n', "\x{1172}" => 'b',  # ㅗㅛㅜㅠ
			"\x{1173}" => 'm', "\x{1175}" => 'l',                                        # ㅡㅣ
			"\x{1162}" => 'o', "\x{1164}" => 'O', "\x{1166}" => 'p', "\x{1168}" => 'P',  # ㅐㅒㅔㅖ
			#종성
			"\x{11A8}" => 'r', "\x{11AB}" => 's', "\x{11AE}" => 'e', "\x{11AF}" => 'f',  # ㄱㄴㄷㄹ
			"\x{11B7}" => 'a', "\x{11B8}" => 'q', "\x{11BA}" => 't', "\x{11BC}" => 'd',  # ㅁㅂㅅㅇ
			"\x{11BD}" => 'w', "\x{11BE}" => 'c', "\x{11BF}" => 'z', "\x{11C0}" => 'x',  # ㅈㅊㅋㅌ
			"\x{11C1}" => 'v', "\x{11C2}" => 'g',                                        # ㅍㅎ
			"\x{11A9}" => 'R', "\x{11BB}" => 'T',                                        # ㄲ ㅆ
			#특수문자
			"\x{20}" => ' ' , "\x{A}" => "\n" , "\x{2E}" => '.' , "\x{2C}" => ',' ,      #Space Enter . ,
			"\x{2D}" => '-' , 
			#Number
			"\x{30}" => '0' , "\x{31}" => '1' , "\x{32}" => '2' , "\x{33}" => '3' ,
			"\x{34}" => '4' , "\x{35}" => '5' , "\x{36}" => '6' , "\x{37}" => '7' ,
			"\x{38}" => '8' , "\x{39}" => '9' ,
	);
	my @jamos =  map { split //, decomposeJamo($_) }split //, decomposeSyllable($str);
	my $keys = '{HAN}';
	foreach (@jamos) { $keys .= $hangle{$_} }
	# print "$strokes";
	return $keys;
}

http://codepad.org/Wa3a4asO


특수문자는 필요한 문자들은 더 추가할 계획이다.

어렵게 한글변환을 끝내고 GuiTest 모듈에 적용시켜 테스트 하려고 하니...

한/영 키의 코드를 모르는 것이다.................




처음에 생각했을 때 외국사람들이 한영키를 배려해놨을리가 없지... 생각하고

키 테스트 프로그램을 몇개 켜놓고 한영키를 꾹꾹 눌러가면서 한영키 값을 찾아보고 있었다.

그렇게 삽질을 하다가 혹시나 해서 GuiTest 모듈을 다시 세부적으로 분석해 보았는데,

GuiTest.pc 파일을 보니 이러한 코드를 확인할 수 있었는데....

1
2
3
4
5
6
7
sub VK_KANA           { 0x15; }
sub VK_HANGEUL        { 0x15; }
sub VK_HANGUL         { 0x15; }
sub VK_JUNJA          { 0x17; }
sub VK_FINAL          { 0x18; }
sub VK_HANJA          { 0x19; }
sub VK_KANJI          { 0x19; }

오.. 이럴수가... 한글에 대해서... 배려를 해 놓았다..

다른나라 사람들도 활용 할 수 있도록 모듈을 설계한

그들의 이식성에 감탄할 수 밖에 없다.


이제 키가 정의된 코드에서 한글 키만 추가하면 한영키를 사용할 수 있다.
 

my %vk = ( 

    ..... 

HAN    => VK_HANGUL(),

 

);


해쉬를 추가한 뒤 간단한 테스트 프로그램을 짜봤다.

Han_Trans.pl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
use strict;
use warnings;    
use Win32::GuiTest;
use Hangle qw/transformation/;
my $key = "글쓰기는 근육과 같습니다.\n".
"더 많이 쓸수록 더 잘 쓸 수 있게 됩니다.\n".
"글을 잘 못쓴다면 간단한 일기를 쓰고, \n".
"블로그도 만들어보고, 창조적인 쓰기 수업을 수강하고, \n".
"4년동안 티격태격 싸워왔던 대학동기나 룸메이트에게 보내는 \n".
"멋진 편지를 써보세요 \n".
"어떤 글이라도 종이에 적기 시작하면 글쓰는 기술이 향상될 겁니다.\n\n".
" - 조엘 온 소프트웨어 \n";
$key = transformation($key);
# print $key;
system("start notepad.exe");
sleep 1;
Win32::GuiTest::SendKeys($key);
sleep 5;
Win32::GuiTest::SendKeys("%{F4}{TAB}{ENTER}");

http://codepad.org/HoxMNqeY


컴파일해서 실행파일까지 만들었으나

이 실행파일은 컴파일 당시 환경과  윈도우 버전이 틀리면 실행되지 않는다.

그리고 3MB 정도로 꾀 큰 용량을 차지하며

패킹을 해봤더니 콘솔창에서 오류가 뜬다. ( 그러면서 실행은 되었다는...)

코드안에 한글이 들어가 있을 경우 컴파일도 안되는 어이없는 일도 생겨...

PAR::Packer 모듈도 조금 더 발전했으면 한다.




- 참고

The Korean Writing System
신고
Trackback 2 Comment 4
2008.11.28 15:52

Win32::Process::Memory


이번에는 프로세스에서 메모리를 읽고 쓸수도 있는 Win32::Process::Memory 에 대해서 알아보자.

이 모듈을 찾게 된 계기는

다른 프로세서에 있는 메모리를 읽어오기 위한 방법이 없을까 

해서 cpan에서 찾는 도중 발견~!


Win32::Process::Memory

read and write memory of other windows process
Win32-Process-Memory-0.20 - 01 May 2004 - Qing-Jie Zhou 


만든지 꾀 오래 된 모듈이다 

2004년 쯤이니.. 벌써 4년이 훨신 지났다.

기본적인 예제를 한번 실행해 보자.

 # 프로세스를 오픈한다.
  my $proc = Win32::Process::Memory->new({ name=>'cmd.exe' });
  # 디버그
  printf "\nTotal Memory = 0x%X\n", $proc->get_memtotal;
  print "\nMemory block list:\n";
  my %memlist = $proc->get_memlist;
  printf "  %08X -> %08X : Len=0x%X\n", $_, $_+$memlist{$_}, $memlist{$_}
      foreach (sort {$a <=> $b} keys %memlist);
  print "\nContent of 0x10004 -> 0x10103\n";
  print $proc->hexdump(0x10004, 0x100);

  # search a sequence of unsigned int16
  print "\nFind a sequence of unsinged int16:\n";
  my @results = $proc->search_u16(92, 87, 105, 110, 51, 50);
  print $proc->hexdump($_, 0x32)."\n" foreach @results;
  # 값을 읽어와서 바꾼다.
  printf "\n0x%X [unsigned int16] : %d\n", 0x10004, $proc->get_u16(0x10004);
  printf "0x%X [unsigned int32] : %d\n", 0x10004, $proc->get_u32(0x10004);
  #$proc->set_u32(0x10004, 55); # 값을 바꾸는것은 위험하다. 시스템이 손상될 수 있다.

  #프로세스를 종료한다.
  undef $proc;
 
이 모듈은 굉장히 유용한 기능이 많은데..

전체 메모리의 양, hex코드로 덤프, 메모리를 검색, 메모리를 변경까지 해준다.


실행화면

D:\Documents and Settings\honey>perl Memory_test.pl

Total Memory = 0x196C000

Memory block list:
  00010000 -> 00011000 : Len=0x1000
  00020000 -> 00021000 : Len=0x1000
  00030000 -> 00035000 : Len=0x5000
  00040000 -> 00140000 : Len=0x100000
  00140000 -> 00143000 : Len=0x3000
  00150000 -> 00163000 : Len=0x13000
  00250000 -> 00256000 : Len=0x6000
  00260000 -> 00268000 : Len=0x8000
  00270000 -> 00286000 : Len=0x16000
  00290000 -> 002D1000 : Len=0x41000
  002E0000 -> 00321000 : Len=0x41000
  00330000 -> 00336000 : Len=0x6000
  00340000 -> 00381000 : Len=0x41000
  00390000 -> 0039B000 : Len=0xB000
  00450000 -> 00452000 : Len=0x2000
  00460000 -> 00468000 : Len=0x8000
  00470000 -> 00471000 : Len=0x1000
  00480000 -> 00481000 : Len=0x1000
  00490000 -> 00492000 : Len=0x2000
  004A0000 -> 004A4000 : Len=0x4000
  004B0000 -> 004B2000 : Len=0x2000
  004C0000 -> 004C8000 : Len=0x8000
  004D0000 -> 004D4000 : Len=0x4000
  004E0000 -> 004E3000 : Len=0x3000
  004F0000 -> 004F3000 : Len=0x3000
  00530000 -> 00633000 : Len=0x103000
  00640000 -> 007B3000 : Len=0x173000
  00940000 -> 00941000 : Len=0x1000
  009C0000 -> 009C1000 : Len=0x1000
  009D0000 -> 009DE000 : Len=0xE000
  009E0000 -> 009E1000 : Len=0x1000
  00A60000 -> 00A62000 : Len=0x2000
  4AD00000 -> 4AD01000 : Len=0x1000
  4AD01000 -> 4AD21000 : Len=0x20000
  4AD21000 -> 4AD22000 : Len=0x1000
  4AD22000 -> 4AD25000 : Len=0x3000
  4AD25000 -> 4AD26000 : Len=0x1000
  4AD26000 -> 4AD29000 : Len=0x3000
  4AD29000 -> 4AD2C000 : Len=0x3000
  4AD2C000 -> 4AD2F000 : Len=0x3000
  4AD2F000 -> 4AD30000 : Len=0x1000
  4AD30000 -> 4AD33000 : Len=0x3000
  4AD33000 -> 4AD39000 : Len=0x6000
  4AD39000 -> 4AD3C000 : Len=0x3000
  4AD3C000 -> 4AD3D000 : Len=0x1000
  4AD3D000 -> 4AD3E000 : Len=0x1000
  4AD3E000 -> 4AD78000 : Len=0x3A000
  5A480000 -> 5A481000 : Len=0x1000
  5A481000 -> 5A4B1000 : Len=0x30000
  5A4B1000 -> 5A4B2000 : Len=0x1000
  5A4B2000 -> 5A4B8000 : Len=0x6000
  5C2E0000 -> 5C2E1000 : Len=0x1000
  5C2E1000 -> 5C2EF000 : Len=0xE000
  5C2EF000 -> 5C2F2000 : Len=0x3000
  5C2F2000 -> 5C303000 : Len=0x11000
  5C303000 -> 5C306000 : Len=0x3000
  5C820000 -> 5C821000 : Len=0x1000
  5C821000 -> 5C892000 : Len=0x71000
  5C892000 -> 5C895000 : Len=0x3000
  5C895000 -> 5C8BA000 : Len=0x25000
  62340000 -> 62341000 : Len=0x1000
  62341000 -> 62346000 : Len=0x5000
  62346000 -> 62347000 : Len=0x1000
  62347000 -> 62349000 : Len=0x2000
  6FD60000 -> 6FD61000 : Len=0x1000
  6FD61000 -> 6FD93000 : Len=0x32000
  6FD93000 -> 6FD94000 : Len=0x1000
  6FD94000 -> 6FD98000 : Len=0x4000
  6FD98000 -> 6FD9C000 : Len=0x4000
  6FD9C000 -> 6FF2A000 : Len=0x18E000
  73F80000 -> 73F81000 : Len=0x1000
  73F81000 -> 73FC5000 : Len=0x44000
  73FC5000 -> 73FCF000 : Len=0xA000
  73FCF000 -> 73FD1000 : Len=0x2000
  73FD1000 -> 73FD4000 : Len=0x3000
  73FD4000 -> 73FD5000 : Len=0x1000
  73FD5000 -> 73FEB000 : Len=0x16000
  762E0000 -> 762E1000 : Len=0x1000
  762E1000 -> 762F6000 : Len=0x15000
  762F6000 -> 762F7000 : Len=0x1000
  762F7000 -> 762FD000 : Len=0x6000
  76970000 -> 76971000 : Len=0x1000
  76971000 -> 76A96000 : Len=0x125000
  76A96000 -> 76A97000 : Len=0x1000
  76A97000 -> 76A9D000 : Len=0x6000
  76A9D000 -> 76AAD000 : Len=0x10000
  76AF0000 -> 76AF1000 : Len=0x1000
  76AF1000 -> 76B10000 : Len=0x1F000
  76B10000 -> 76B11000 : Len=0x1000
  76B11000 -> 76B12000 : Len=0x1000
  76B12000 -> 76B1B000 : Len=0x9000
  76D90000 -> 76D91000 : Len=0x1000
  76D91000 -> 76DAE000 : Len=0x1D000
  76DAE000 -> 76DAF000 : Len=0x1000
  76DAF000 -> 76DB2000 : Len=0x3000
  770D0000 -> 770D1000 : Len=0x1000
  770D1000 -> 77151000 : Len=0x80000
  77151000 -> 77152000 : Len=0x1000
  77152000 -> 77154000 : Len=0x2000
  77154000 -> 7715B000 : Len=0x7000
  77160000 -> 77161000 : Len=0x1000
  77161000 -> 771F2000 : Len=0x91000
  771F2000 -> 771F3000 : Len=0x1000
  771F3000 -> 77263000 : Len=0x70000
  77B90000 -> 77B91000 : Len=0x1000
  77B91000 -> 77BA1000 : Len=0x10000
  77BA1000 -> 77BA2000 : Len=0x1000
  77BA2000 -> 77BA5000 : Len=0x3000
  77BB0000 -> 77BB1000 : Len=0x1000
  77BB1000 -> 77BB5000 : Len=0x4000
  77BB5000 -> 77BB6000 : Len=0x1000
  77BB6000 -> 77BB8000 : Len=0x2000
  77BC0000 -> 77BC1000 : Len=0x1000
  77BC1000 -> 77C0D000 : Len=0x4C000
  77C0D000 -> 77C0F000 : Len=0x2000
  77C0F000 -> 77C10000 : Len=0x1000
  77C10000 -> 77C11000 : Len=0x1000
  77C11000 -> 77C14000 : Len=0x3000
  77C14000 -> 77C18000 : Len=0x4000
  77CF0000 -> 77CF1000 : Len=0x1000
  77CF1000 -> 77D51000 : Len=0x60000
  77D51000 -> 77D52000 : Len=0x1000
  77D52000 -> 77D53000 : Len=0x1000
  77D53000 -> 77D80000 : Len=0x2D000
  77D80000 -> 77D81000 : Len=0x1000
  77D81000 -> 77E0B000 : Len=0x8A000
  77E0B000 -> 77E0C000 : Len=0x1000
  77E0C000 -> 77E12000 : Len=0x6000
  77E20000 -> 77E21000 : Len=0x1000
  77E21000 -> 77E64000 : Len=0x43000
  77E64000 -> 77E66000 : Len=0x2000
  77E66000 -> 77E69000 : Len=0x3000
  77E70000 -> 77E71000 : Len=0x1000
  77E71000 -> 77EDD000 : Len=0x6C000
  77EDD000 -> 77EDE000 : Len=0x1000
  77EDE000 -> 77EE6000 : Len=0x8000
  77EF0000 -> 77EF1000 : Len=0x1000
  77EF1000 -> 77EFE000 : Len=0xD000
  77EFE000 -> 77EFF000 : Len=0x1000
  77EFF000 -> 77F01000 : Len=0x2000
  77F50000 -> 77F51000 : Len=0x1000
  77F51000 -> 77FC6000 : Len=0x75000
  77FC6000 -> 77FC7000 : Len=0x1000
  77FC7000 -> 77FCB000 : Len=0x4000
  77FCB000 -> 77FF8000 : Len=0x2D000
  7C800000 -> 7C801000 : Len=0x1000
  7C801000 -> 7C885000 : Len=0x84000
  7C885000 -> 7C888000 : Len=0x3000
  7C888000 -> 7C88A000 : Len=0x2000
  7C88A000 -> 7C930000 : Len=0xA6000
  7C930000 -> 7C931000 : Len=0x1000
  7C931000 -> 7C9AB000 : Len=0x7A000
  7C9AB000 -> 7C9AE000 : Len=0x3000
  7C9AE000 -> 7C9AF000 : Len=0x1000
  7C9AF000 -> 7C9B0000 : Len=0x1000
  7C9B0000 -> 7C9CB000 : Len=0x1B000
  7D5A0000 -> 7D5A1000 : Len=0x1000
  7D5A1000 -> 7D79F000 : Len=0x1FE000
  7D79F000 -> 7D7AF000 : Len=0x10000
  7D7AF000 -> 7D7B5000 : Len=0x6000
  7D7B5000 -> 7D7BC000 : Len=0x7000
  7D7BC000 -> 7DD9D000 : Len=0x5E1000
  7E8C0000 -> 7E8C1000 : Len=0x1000
  7E8C1000 -> 7E961000 : Len=0xA0000
  7E961000 -> 7E963000 : Len=0x2000
  7E963000 -> 7E971000 : Len=0xE000
  7F6F0000 -> 7F6F7000 : Len=0x7000
  7FFA0000 -> 7FFD3000 : Len=0x33000
  7FFD4000 -> 7FFD5000 : Len=0x1000
  7FFDF000 -> 7FFE0000 : Len=0x1000
  7FFE0000 -> 7FFE1000 : Len=0x1000

Content of 0x10004 -> 0x10103
00010000 :             3A 00 3D 00 3A 00 3A 00 5C 00 00 00 :     :.=.:.:.\...
00010010 : 3D 00 44 00 3A 00 3D 00 44 00 3A 00 5C 00 44 00 : =.D.:.=.D.:.\.D.
00010020 : 6F 00 63 00 75 00 6D 00 65 00 6E 00 74 00 73 00 : o.c.u.m.e.n.t.s.
00010030 : 20 00 61 00 6E 00 64 00 20 00 53 00 65 00 74 00 :  .a.n.d. .S.e.t.
00010040 : 74 00 69 00 6E 00 67 00 73 00 5C 00 68 00 6F 00 : t.i.n.g.s.\.h.o.
00010050 : 6E 00 65 00 79 00 00 00 3D 00 45 00 78 00 69 00 : n.e.y...=.E.x.i.
00010060 : 74 00 43 00 6F 00 64 00 65 00 3D 00 30 00 30 00 : t.C.o.d.e.=.0.0.
00010070 : 30 00 30 00 30 00 30 00 30 00 30 00 00 00 41 00 : 0.0.0.0.0.0...A.
00010080 : 4C 00 4C 00 55 00 53 00 45 00 52 00 53 00 50 00 : L.L.U.S.E.R.S.P.
00010090 : 52 00 4F 00 46 00 49 00 4C 00 45 00 3D 00 44 00 : R.O.F.I.L.E.=.D.
000100A0 : 3A 00 5C 00 44 00 6F 00 63 00 75 00 6D 00 65 00 : :.\.D.o.c.u.m.e.
000100B0 : 6E 00 74 00 73 00 20 00 61 00 6E 00 64 00 20 00 : n.t.s. .a.n.d. .
000100C0 : 53 00 65 00 74 00 74 00 69 00 6E 00 67 00 73 00 : S.e.t.t.i.n.g.s.
000100D0 : 5C 00 41 00 6C 00 6C 00 20 00 55 00 73 00 65 00 : \.A.l.l. .U.s.e.
000100E0 : 72 00 73 00 00 00 41 00 50 00 50 00 44 00 41 00 : r.s...A.P.P.D.A.
000100F0 : 54 00 41 00 3D 00 44 00 3A 00 5C 00 44 00 6F 00 : T.A.=.D.:.\.D.o.
00010100 : 63 00 75 00                                     : c.u.

Find a sequence of unsinged int16:
0x10004 [unsigned int32] : 3997754


여러가지 함수중 메모리 덤프가 굉장히 유용해 보인다.


사용법을 알았으니 실전으로 테스트를 해보자.


먼저 예전에 조사해두었던 지뢰찾기의  각 블럭의 메모리 주소들을 ollydbg로 확인한다.




0x01005340 부터 0x01005490까지

초급 지뢰찾기의 형태가 출력되어 있는것을 확인 할 수 있다.


이 블럭의 값들이 이해를 돕기 위해 해당 블럭의 값들을 정리해 보았다.

 

16진수

블록의 용도

0x10

테두리

0x0F

오픈되지 않은 블록

0x0E

체크한 지뢰

0x0D

물음표

0x40~0x48

주변의 지뢰갯수

0x8F

오픈되지 않은 지뢰

0xCC

빨간색 지뢰(지뢰가 터졌을 때)

0x8A

오픈된 지뢰(게임종료시)




실제 게임화면과 비슷하게 정규식을 사용하여 메모리 덤프한 파일들을 보기좋게 정리하는 코드를 짜봤다.

항상 생각하지만 정규표현식이 아직 많이 부족해서..

더 좋은 방법으로 문자열을 뽑아내고 싶은 마음이 든다.




1
2
3
4
5
6
7
8
9
10
11
use Win32::Process::Memory;

my $proc = Win32::Process::Memory->new({ name=>'winmine.exe' });
printf "\nTotal Memory = 0x%X\n", $proc->get_memtotal;
print "\nContent of 0x01005340 -> 0x01005490\n";
my $block = $proc->hexdump(0x01005340, 0x150);
my @blocks = $block =~ m/10\s.*\s10/g;
$block = join "\n",@blocks;
$block =~ s/10//g;
print "$block";
undef $proc;


http://codepad.org/nviziVV4


깔끔하게 지뢰찾기의 블럭들이 정렬되어 출력된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
D:\Documents and Settings\honey>perl winmine.pl

Total Memory = 0x1B64000

Content of 0x01005340 -> 0x01005490

 0F 0F 0F 8F 0F 0F 0F 0F 0F
 0F 0F 0F 0F 0F 0F 0F 0F 0F
 0F 0F 0F 0F 8F 8F 0F 0F 0F
 0F 0F 0F 0F 0F 0F 0F 0F 0F
 0F 0F 0F 0F 0F 0F 0F 0F 0F
 0F 0F 0F 0F 0F 8F 0F 0F 0F
 8F 0F 8F 0F 0F 0F 0F 0F 0F
 0F 8F 0F 0F 8F 0F 0F 0F 0F
 0F 0F 8F 0F 0F 0F 8F 0F 0F


이제 게임으로 !!




실제로 출력화면을 보고 지뢰찾기를 한 것인데... 시간은 신경쓰지말자;;


보면서 하니깐 더 안되는... OTL...

위의 출력된 지뢰위치와 그림파일의 지뢰위치가 동일한 것을 확인 할 수 있다.



사용자정의로 말도안되는 지뢰찾기맵을 만들더라도 가볍게 클리어 해주자...





Win32::Process::Memory는 메모리를 write도 가능하기 때문에

위의 작성한 코드를 조금만 수정하여..

모든 블럭의 값을 수정하여 지뢰로 만들어 보았다.




원래는 이런 구성은 만들어 질 수 없으며...

생각만해도 아찔한 영상이다;;



전에 소개한 Win32::GuiTest 모듈을 사용하여

MineFinder를 구현해 보았다.

자동으로 Mine을 찾아서 게임을 클리어 해주는 프로그램인데...



지뢰찾기를 실행시킨 뒤

위의 코드와 같이 정규식으로 뽑아낸 값을 통해서 비교를 한 뒤

해당 위치가 지뢰일 때는 우클릭 그 위외에는 모두 좌클릭을 해 주었다.


머릿속으로 생각한 뒤 구현하려니 좀 버벅되긴 했지만... 

이론으로 충분히 가능했기 때문에 구현하는데 그리 오래 걸리진 않았다.


초급으로 만드는 코드를 처음에 실행한다 ㅡ_ㅡ;

반 강제적으로 초급만 되도록... 설정하였다 ( 중급 고급이 다 되게 하는것이 조금 빡세서...)






대부분 3초안에 클리어 할 수 있으며 빠르면 1초안에 클리어도 가능하다.







Good Job  :- )
신고
Trackback 1 Comment 6
2008.11.17 20:04

Win32::GuiTest - Perl GUI Test Utilities.


최근 Gtk를 사용하여 이것저것 실습을 하던 중

perl로 Windows api를 다루는 모듈은 없을까 cpan에서 

Search를 해보던중 흥미로운 모듈을 발견했다.


Win32::GuiTest

Perl GUI Test Utilities. 
Win32-GuiTest-1.56****  (2 Reviews) - 02 Oct 2008 - Dmitry Karasik


Perl GUI Test Utilities...

갱신된지 얼마 되지 않은 이 모듈은 뭘까?

  use Win32::GuiTest qw(FindWindowLike GetWindowText 
    SetForegroundWindow SendKeys);

  $Win32::GuiTest::debug = 0; # Set to "1" to enable verbose mode

  my @windows = FindWindowLike(0, "^Microsoft Excel", "^XLMAIN\$");
  for (@windows) {
      print "$_>\t'", GetWindowText($_), "'\n";
      SetForegroundWindow($_);
      SendKeys("%fn~a{TAB}b{TAB}{BS}{DOWN}");
  }

코드를 대략 살펴보니 보니  FindWindowLike 함수를 사용하여 윈도우 창을 찾고

그 창에 여러 키를 입력하는 코드였다.

일단 설치를 하고 SYSNOPSIS의 기본 코드를 실행을 시켜보니...

(나의 스타일이 결과부터 보자식이라;;)


실행과 동시에 종료되어 버렸다...

아.. 그렇다;; Excel창이 없으니 자동 종료가 되어버렸....


Excel을 실행 시킨후 다시 perl 프로그램을 실행시키니



헉... 엑셀 시트에 n과 a, b 문자를 출력하고 있다.

왠지 흥미롭지 않는가? +_+



전체적으로 key 뿐만아니라 Mouse 까지 다루고 있으며

SendKeys함수의 세부적인 Action 까지 상세하게 다루고 있다.

이것 하나만 있으면 엑셀을 사용하는 사람은... 

조금 더 편하게 문서를 정리 할 수 있지 않을까?




사용법을 완벽하게 익히기에 예제가 조금 부족한 느낌이 들었는데


Win32::GuiTest::Examples

collection of the scripts from eg 
Win32-GuiTest-1.56****  (2 Reviews) - 02 Oct 2008 - Dmitry Karasik


예제까지 확실하게 Cpan에 올려놓으셨다..




Examples에는 총 26개의 예제가 있으며 재밌는 코드를 소개하자면!!


   #!perl -w
    #
    # Draw an X and a box around it
    #
    use strict;
    use Win32::GuiTest qw(FindWindowLike SetForegroundWindow 
        SendMouse MouseMoveAbsPix SendLButtonDown SendLButtonUp);
    
    system("start /max mspaint");
    sleep 2;
    my @windows = FindWindowLike(0, "Paint", "");
    die "Could not find Paint\n" if not @windows;
    
    SetForegroundWindow($windows[0]);
    sleep 1;
    
    #Using low level functions
    MouseMoveAbsPix(100,100);
    SendLButtonDown();
    MouseMoveAbsPix(300,300);
    SendLButtonUp();
    
    
    sleep 1;
    
    MouseMoveAbsPix(100,300);
    SendLButtonDown();
    MouseMoveAbsPix(300,100);
    SendLButtonUp();
    
    sleep 1;
        
    MouseMoveAbsPix(100,100);
    SendLButtonDown();
    MouseMoveAbsPix(300,100);
    MouseMoveAbsPix(300,300);
    MouseMoveAbsPix(100,300);
    MouseMoveAbsPix(100,100);
    SendLButtonUp();


윈도우 창을 찾을 때 한글을 고려하자면...

my @windows = FindWindowLike(0, "Paint", "");

이런식으로 고쳐주셔야...

my @windows = FindWindowLike(0, "제목 없음 - 그림판", "");



시스템 함수를 사용하여 mspaint 를 실행시킨후

마우스를 이동시키며 정사각형안에 X가 들어있는 그림을 그리는 코드이다.

실용성은 없어보이지만 볼거리가 있는 코드라 넣어놓는다






그 이외에...

계산기를 실행하여 자동으로 숫자와 연산자를 입력하여 결과값을 구해주는 코드

노트패드에 글을 쓴 뒤 자동으로 종료해주는 코드, 

//이건 재미있어서 실행파일로 만들어 보았다.




카드놀이를 실행한뒤 이것저것 만져주는 코드,

컴퓨터의 제어판의 여러 목록들을 실행하고 종료하는 코드,

윈도우의 모든 창을 찾아주는 코드,

해당 창을 찾아 캡쳐를 한 뒤 자동으로 저장해주는 코드  등 // 위험한 느낌이 들었던..;

유용한 코드들이 많이 보였다.



보안적인 면에서는 백그라운드로 실행되는 것이 아니기 때문에

해킹툴보다는 조크바이러스 정도로 밖에 안될듯...


나 너 해킹했어요~ 이렇게 알려주는 것이라...

비주얼 적인 면에서는 효과가 뛰어날 것이라 본다.




오토마우스 오토키보드 같은 프로그램이 있긴 하지만...

perl을 사용하여 직접 프로그램을 만들어 보는것도

흥미로운 작업이 아닐까 생각된다^^
신고
Trackback 5 Comment 2