[ Delphi - 피라미터 가로채기 ]
[1] 커맨드 라인 인자값 받기
ParamStr function
Index 번째 command-line 파라미터를 반환합니다.
Unit
System
Category
command line utilities
Delphi syntax:
function ParamStr(Index: Integer): string;
C++ syntax:
extern PACKAGE AnsiString __fastcall ParamStr(int Index);
Description
Index 번째 command-line 파라미터를 반환합니다.
Index 가 ParamCount 보다 클 경우 빈 문자열을 반환합니다.
예를들어, Index 가 2 이면 두번째 파라미터를 반환합니다.
Windows 에서 ParamStr(0) 은 실행파일의 FullName 을 반환합니다.
Linux 에서 ParamStr(0) 은 파라미터를 제외한 실행 명령을 반환합니다.
참고: 쌍 따옴표로 묶인 문자열은 하나의 파라미터로 취급됩니다.
-------------------------------------------------------------
위는 도움말 번역입니다.
커맨드라인 툴을 만들게 되면 파라미터가 거의 필수입니다.
온라인 게임중, 웹에서 접속하여 런쳐를 실행하는 방식의 경우
암호화된 인증문자열(ID/PASS 로 암호화된)을 파라미터로 전달하게되며
이를 가로채는 간단한 코딩으로 해킹이 가능해지는 황당한 일 도 있습니다.
(실제 모 온라인 게임에서 해보고 깜짝놀랐어요~)
몇가지 사용법을 적어보겠습니다.
1. 실행파일명(경로제외) 구하기
Str := ExtractFileName(ParamStr(0));
2. 실행경로명 구하기
Str := ExtractFilePath(ParamStr(0));
3. 실행파일과 이름이 같은 다른 파일명 구하기
Str := ChangeFileExt(ParamStr(0), '.ini');
4. 실행파일을 제외한 파라미터 전체 합치기
str := '';
for I := 1 to ParamCount do
str := str + '"' + ParamStr(I) + '" ';
참고: ParamStr 의 Index 가 0 이면 실행파일명, 1..ParamCount 는 파라미터입니다.(ParamCouont - 1 아님)
추가: 파라미터에 공백이 있는경우 (Program Files 폴더명 같은경우) 그냥 넘겨주면 여러 파라미터로 인식하므로 " " 따옴표로 감싸줍니다.
[ 2 ] 파일 속성 변경하기
FileSetAttr function
-----------------
명시된 파일의 속성을 설정한다.
유닛
SysUtils
분류
파일 관리 루틴
델파이 문법:
function FileSetAttr(const FileName: string; Attr: Integer): Integer;
C++ 문법:
extern PACKAGE int __fastcall FileSetAttr(const AnsiString FileName, int Attr);
설명
FileSetAttr 은 FileName 이름의 파일 속성을 Attr 로 변경한다.
Attr 값은 파일 속성 상수의 조합으로 이루어진다, 다음 예를 보라:
FileSetAttr('MyFile.sys', faReadOnly or faSysFile); // Delphi
FileSetAttr("MyFile.sys", faReadOnly | faSysFile); // C++
FileSetAttr 이 성공적으로 끝나면 0 을 반환한다. 그 외에는 에러코드를 반환한다.
Note: FileSetAttr 은 Windows 에만 적용된다.
파일 속성 상수 (Constant = Value, Description)
faReadOnly = 1, Read-only files
faHidden = 2, Hidden files
faSysFile = 4, System files
faVolumeID = 8, Volume ID files
faDirectory = 16, Directory files
faArchive = 32, Archive files
faSymLink = 64, Symbolic link
faAnyFile = 71, Any file
예제) 자기 자신을 시스템파일, 숨김파일, 읽기전용 속성으로 세팅하기.
FileSetAttr(ParamStr(0), faSystem or faHidden or faReadOnly);
[ 3 ] 문자열 처리하기 [ 1/2 ]
TStringList
-----------
TStringList 는 문자열 목록을 유지합니다.
유닛
Classes
설명
문자열 목록을 저장하고 다루기 위하여 문자열 목록 객체를 사용합니다.
TStringList 는 TStrings 의 추상 속성과 메소드,
● 목록의 문자열 정렬을 위한 새로운 속성, 이벤트, 그리고 메소드를 구현합니다.
● 정렬된 목록에서는 중복된 문자열을 금지합니다.
● 목록의 내용 변화에 응답합니다.
● 문자열 배치, 정렬, 그리고 확인 등의 중복 처리에 대소문자구분 또는 대소문자 비구분의 두가지 방법의 제어를 합니다.
(전체 속성, 메소드, 이벤트 설명은 제외합니다.)
---------------------------------------------------------------------------
Count 속성 (TStringList)
----------------------------
목록에 있는 문자열의 숫자를 나타냅니다.
Delphi 문법:
property Count: Integer;
C++ 문법:
__property int Count = {read=GetCount, nodefault};
설명
목록의 모든 문자열에 대한 반복, 또는 목록의 마지막 문자열의 위치와 상대적인 위치에 문자열을 위치시키기 위해 Count 를 사용합니다.
---------------------------------------------------------------------------
Strings 속성 (TStringList)
------------------------------
0 기반 인덱스로 문자열을 참조합니다.
Delphi 문법:
property Strings[Index: Integer]: string; default;
C++ 문법:
__property AnsiString Strings[int Index] = {read=Get, write=Put};
설명
부분적 위치의 문자열을 읽거나 수정하는데 Strings 를 사용합니다.
Index 는 문자열의 위치입니다, 0은 첫 문자열의 위치이고, 1은 두번째 문자열의 위치이며, 나머지도 동일 규칙입니다.
델파이에서, Strings 는 StringList 객체의 기본 속성입니다.
Strings 지시자는 생략될 수 있습니다.
예를들면, 아래 두줄의 코드는 서로 다르나 같은 역할을 합니다:
MyStringList.Strings[0] := 'This is the first string';
MyStringList[0] := 'This is the first string';
길어서 메소드와 예제 설명은 나눕니다~_~
설명은 TStringList 를 모두 설명하는 것이 아닌 자주쓰이는 또 설명할 필요가 있는 것만 도움말을 해석해 올립니다.
이 글을 다 외울 필요는 없고 시간나면 읽어 보시고, 아니면 이런 역할을 하는 객체구나, 이런 속성이 있구나만 읽고 넘어가시길...
[ 4 ] 문자열 처리하기 [ 2/2 ]
---------------------------------------------------------------------------
TStringList
---------------------------------------------------------------------------
Add 메소드 (TStringList)
------------------------
목록에 새로운 문자열을 추가합니다.
Delphi 문법:
function Add(const S: string): Integer; override;
C++ 문법:
virtual int __fastcall Add(const AnsiString S);
설명
S 에 입력된 문자열을 목록에 추가합니다.
목록이 정렬상태이면, S 는 정렬순서의 적절한 위치에 추가됩니다.
목록이 정렬상태가 아니라면, S 는 목록의 마지막에 추가됩니다.
Add 는 추가된 문자열의 위치를 반환합니다, 맨 처음에 추가되었다면 0을 반환합니다
참고: 정렬상태의 목록일때, S 가 이미 등록된 문자열과 동일하고 Duplicates 속성이 dupError 라면
Add 는 EListError 예외를 발생시킵니다.
Duplicates 가 dupIgnore 라면 Add 는 기존 문자열의 Index 를 반환합니다.
---------------------------------------------------------------------------
Clear 메소드 (TStringList)
--------------------------
목록의 모든 문자열을 제거합니다.
Delphi 문법:
procedure Clear; override;
C++ 문법:
virtual void __fastcall Clear(void);
설명
Clear 호출은 목록의 문자열을 모두 비웁니다.
모든 연결된 객체 또한 제거됩니다.
그러나, 객체는 스스로 Free 되지 않습니다.
(추가:StringList 이지만 TObject 형을 연결해서 추가할 수 있기 때문에 이 경우에 이런 상황이 발생하며, 따로 처리를 해줘야합니다.)
---------------------------------------------------------------------------
LoadFromFile 메소드 (TStrings)
------------------------------
명시된 파일에서 문자열 목록으르 불러옵니다.
Delphi 문법:
procedure LoadFromFile(const FileName: string); virtual;
C++ 문법:
virtual void __fastcall LoadFromFile(const AnsiString FileName);
설명
LoadFromFile 을 호출하면 FileName 에 명시된 파일에서 TStrings 객체 형식의 목록을 가져와서 채웁니다.
LoadFromFile 은 먼저 목록을 초기화합니다.
그런 다음, Carriage Return(#13) 또는 Linefeed(#10) 문자로 줄을 구분하여 각 줄을 목록에 추가합니다.
참고: LoadFromFile 은 내부적으로 문자를 추가하는데 Add 메소드를 이용합니다.
---------------------------------------------------------------------------
SaveToFile method (TStrings)
----------------------------
문자열 목록을 명시된 파일로 저장합니다.
Delphi 문법:
procedure SaveToFile(const FileName: string); virtual;
C++ 문법:
virtual void __fastcall SaveToFile(const AnsiString FileName);
설명
SaveToFile 호출은 FileName 에 명시된 파일에 문자열 목록을 저장합니다.
각 문자열은 파일에 라인으로 구분되어 저장됩니다.
리눅스에서, SaveToFile 은 목록에 나타난 그대로 저장됩니다.
만약 마지막 문자열이 end-of-line 마크로 끝자지 않을 경우,
결과 파일은 몇몇 에디터에서 완성되지 않았다고 판단될 것입니다.
(추가:이 부분은 리눅스에서 해보질 않아 저도 이해가 안되네요--;)
---------------------------------------------------------------------------
예제) FileName 에 명시된 파일 마지막에 Msg 에 넘어온 문자열을 추가하여 저장하기
procedure AppendFile(FileName, Msg: String);
var
S: TStrings;
begin
S := TStringList.Create;
if S = nil then
raise Exception.Create('메모리 쓰기 실패');
try
if FileExists(FileName) then
S.LoadFromFile(FileName);
S.Add(Msg);
S.SaveToFile(FileName);
finally
S.Free;
end;
end;
TStrings 형 변수에 TStringList 를 생성하는 것은 다형성의 개념이 적용되기 때문이겠죠.
델파이에서 문자열 객체는 대부분 TStrings 에서 상속받습니다. (아마 전부일 듯 합니다)
대표적인 예로 TMemo 의 Lines 속성이 TStrings 형 속성인데 내부적으로 TMemoStrings 형으로 생성됩니다.
TMemoStrings 는 TStringList 에 비해 기능이 좀 적은 듯 하네요.
이상 도움말 내용을 번역하다보니 저도 모르던 부분이 많이 나오네요.
특히 이번것은...ㅎㅎ
이말은 곧 예제만 봐도 사용에는 지장이 없다는 뜻? ㅋㅋ
[ 5 ] 파일삭제 + 인자값으로 실행시키기
도움말 번역은 빼겠습니다. (혼자 지쳐서 -_-;)
직접 한번 번역해서 읽어보세요.
한번 읽었어도 또 읽어보면 잊혀진 내용들도 다시 상기되고 의미있네요.
1. 파일삭제
DeleteFile('C:\a.txt');
c:\a.txt 를 삭제하는 코드입니다. 간단하죠.
2. 프로그램 실행
ShellExecute(0, 'open',
'C:\Windows\system32\notepad.exe',
'C:\a.txt', nil, SW_SHOW);
C:\a.txt 를 메모장으로 여는 코드입니다.
첫째 인자값은 부모윈도우의 핸들입니다. 안정해주려고 0 을 넣었습니다. HWND 형 변수가 nil 이 아닌 0입니다.
둘째 인자값은 명령입니다. open: 열기, print: 인쇄, explorer: 탐색기 열기
세째 인자값은 대상을 가리킵니다. open 의 경우는 파일명 또는 웹주소가 올 수 있습니다.
네째 인자값은 실행파일의 파라미터를 지정합니다. 없을경우 nil 입니다.
닷째 인자값은 기본 디렉토리 설정인데... 보통 귀찮아서 nil 합니다. (기본 디렉토리인줄 방금 알다니 ㅡ_ㅡ;;)
엿째 인자값은 보여주는 방식으로 SW_SHOW 는 일반적으로 보여주며 여는 것입니다.
도움말 빼니 간단하게 끝나네요;;
나머지는 이 글의 부모글을 보세요~
[ 5 ] 마무리
덧글로 길게 썼는데 이해 안되시면 그냥 마지막 예제 부분만 보고 사용법만 알면 그만입니다.
이 글은 덧글의 내용을 종합해 적용해보는 글입니다 ~_~
New - Others 에서 Console 을 선택해 새 프로젝트를 생성하고 아래와 같이 만들어봅시다.
program WebIntercept;
{$APPTYPE CONSOLE}
uses
Classes,
ShellAPI,
SysUtils;
const
SW_SHOW = 5; // Defined in Windows unit. Windows 유닛을 빼기 위해 따로 정의함
var
I: Integer;
Param: String;
DataFile: String;
// TStringList 예제에 적힌 것입니다. 관련 덧글을 보세요.
procedure AppendFile(FileName, Msg: String);
var
S: TStrings;
begin
S := TStringList.Create;
if S = nil then raise Exception.Create('메모리 쓰기 실패');
try
if FileExists(FileName) then
S.LoadFromFile(FileName);
S.Add(Msg);
S.SaveToFile(FileName);
finally
S.Free;
end;
end;
begin
try
// 내 자신에게 ReadOnly 속성을 겁니다. 모 게임에 적용결과 이 경우 런쳐업데이트를 무시할 수 있습니다.
// 런쳐가 업데이트되면 이걸 다시 설치해야되니~_~
FileSetAttr(ParamStr(0), faArchive or faReadOnly);
// 넘어 온 파라미터를 가로채서 쌍따옴표로 구분해 줍니다.
Param := '';
for I := 1 to ParamCount do
Param := Param + ' "' + ParamStr(I) + '"';
Param := Trim(Param);
// DataFile 의 이름은 본 실행파일명.log 로 합니다.
DataFile := ChangeFileExt(ParamStr(0), '.log');
// DataFile 에 Param 에 저장된 파라미터 값을 추가합니다.
AppendFile(DataFile, Param);
// 실행파일명org.exe 를 실행합니다. 원래 실행파일을 이 이름으로 변경해 놓아야겠죠.
// 파라미터에 넘어온 파라미터를 그대로 넘겨주어 눈치 못채게!!!
ShellExecute(0, 'open',
PAnsiChar(ChangeFileExt(ParamStr(0), 'org.exe')),
PAnsiChar(Param), nil, SW_SHOW);
except
end;
end.
이렇게 하면 파라미터 가로채서 저장까지 완료입니다.
try
except
end;
이부분을 설명을 안했나요.
중간중간 예외 처리를 해놓고 이렇게 전체를 묶어버리면 에러처리가 안되죠.
왜냐하면, 에러를 발생시키면 눈치채잖아요.
이순신 장군님의 "나의 죽음을 적에게 알리지 말라" 전략입니다.
원래는 INI 파일 사용과 FTP 업로드도 넣으려고 했으나 길어지는 것도 귀찮고(기능 한두개가 저 위의 코드보다 많아지는 ㅡㅡ)
다 만들어주면 많은 이들이 쉽게 악용할 것을 고려하여 실시간 전송은 뺐습니다.
언젠가 기회가 되면 이 글과 관련짓지는 않겠지만 글을 쓰게 되겠죠.
끝.
File List
첨부 파일 없음