commit 0ccdbd2cc9ba92c3a32e8d611d00bfb55fbb291a Author: Darkness Date: Mon Jun 17 19:45:20 2019 +0900 add diff --git a/ChangeDnsToIp.cs b/ChangeDnsToIp.cs new file mode 100644 index 0000000..bb5b819 --- /dev/null +++ b/ChangeDnsToIp.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; + +/* +게임 접속시 DNS를 IP로 변경하여 게임 서버 접속요청 클래스 +*/ +namespace ShiningLoreLauncher +{ + class ChangeDnsToIp + { + public string ipAddressGet() + { + //DNS 이름 저장 + string HostName = ""; + + //ip 주소 저장 + string ipAddressName = ""; + + HostName = "youid.iptime.org"; + //실제 name 을 가져오기 위해 IPHostEntry을 이용 + + IPHostEntry hostEntry = Dns.GetHostEntry(HostName); + + //IP 주소를 찾는다. + foreach (IPAddress ip in hostEntry.AddressList) + { + ipAddressName = ip.ToString(); + } + return ipAddressName; + } + } +} diff --git a/FileCheck/FileChecking.cs b/FileCheck/FileChecking.cs new file mode 100644 index 0000000..45ff573 --- /dev/null +++ b/FileCheck/FileChecking.cs @@ -0,0 +1,83 @@ +using ShiningLoreLauncher.Class; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Security.Cryptography; +using System.Text; +using System.Windows.Forms; + +/* +sha1 을 이용하여 서버와 클라이언트간의 위변조 검출 클래스 +*/ + +namespace ShiningLoreLauncher +{ + class FileChecking + { + //해시코드 생성하여 리턴 + public static string GetChecksum(string sPathFile) + { + if (!File.Exists(sPathFile)) + { + return null; + } + + using (FileStream stream = File.OpenRead(sPathFile)) + { + MD5 md5 = new MD5CryptoServiceProvider(); + byte[] byteChecksum = md5.ComputeHash(stream); + return BitConverter.ToString(byteChecksum).Replace("-", String.Empty); + } + } + + internal static string GetChecksum(object p) + { + throw new NotImplementedException(); + } + + //클라이언트와 서버간의 해시코드 대조 + public static bool CheckSumFIle() + { + //파일 체크 변수 + string celFileCheck; //플레이 컴퓨터파일 해시코드 + string serFileCheck; // 서버 컴퓨터파일 해시코드\ + + bool fileCheckBool = false; + //서버 클라이언트 해시코드 + string[] serfileName = {"Budt.txt", "Dhs.txt", "Dkjsin.txt", "Ehdt.txt", "Ikdmn.txt", "Lkezmd.txt", + "Osa.txt" , "Qods.txt" , "SlOnline.txt"}; + //클라이언트 해시코드 + string[] celfileName = { @"\Data\Budt.bin", @"\Data\Dhs.bin", @"\Data\Dkjsin.bin", @"\Data\Ehdt.bin", @"\Data\Ikdmn.bin", @"\Data\Lkezmd.bin", + @"\Data\Osa.bin" , @"\Data\Qods.bin" , @"\SlOnline.exe"}; + + //서버 해시코드 대조하기 위해 해시코드 호출 + WebClient webFileRead = new WebClient(); + + for (int i = 0; i < serfileName.Length; i++) + { + //서버에 있는 txt 파일을 읽어서 해시코드 호출한다. + Stream stream = webFileRead.OpenRead(new Uri(@"http://youid.iptime.org:9999/updateFile/" + serfileName[i])); + StreamReader reader = new StreamReader(stream); + serFileCheck = reader.ReadLine(); + webFileRead.Dispose(); + + //클라이언트에 있는 파일 해시코드를 생성하고 변수에 저장 + celFileCheck = FileChecking.GetChecksum(Application.StartupPath + celfileName[i]); + + if (celFileCheck != serFileCheck) + { + MessageBox.Show("클라이언트 개조가 발견되었습니다. 프로그램을 종료합니다."); + return fileCheckBool = true; + } + else + { + //MessageBox.Show("깨끗한 클라이언트입니다."); + } + } + + return fileCheckBool; + } + } +} diff --git a/OptionSet.cs b/OptionSet.cs new file mode 100644 index 0000000..4e02047 --- /dev/null +++ b/OptionSet.cs @@ -0,0 +1,145 @@ +using Microsoft.Win32; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; + +namespace ShiningLoreLauncher.Class +{ + partial class OptionSet + { + + //창모드 전체화면 설정값 + public static int resolutionNum = 1; + //옵션 체크용 + public static bool optionCheck = false; + + //옵션 메소드 + public static void optionSet() + { + Form form2 = new Form(); + CheckBox cb1 = new CheckBox(); + RadioButton rb1 = new RadioButton(); + RadioButton rb2 = new RadioButton(); + RadioButton rb3 = new RadioButton(); + Button okBt = new Button(); + PictureBox pk1 = new PictureBox(); + + Image imageSet = ShiningLoreLauncher.Properties.Resources.dsa; + + + cb1.Text = "창모드"; + rb1.Text = "800 x 600"; + rb2.Text = "1024 x 768"; + rb3.Text = "1152 x 864"; + okBt.Text = "설정완료"; + + //폼 사이즈 고정 + form2.FormBorderStyle = FormBorderStyle.FixedSingle; + form2.MaximizeBox = false; + + form2.Size = new Size(250, 200); + cb1.Size = new Size(100, 30); + rb1.Size = new Size(100, 30); + rb2.Size = new Size(100, 30); + rb3.Size = new Size(100, 30); + okBt.Size = new Size(100, 30); + pk1.Size = new Size(147, 192); + + + + cb1.Location = new Point(0, 0); + rb1.Location = new Point(0, 30); + rb2.Location = new Point(0, 60); + rb3.Location = new Point(0, 90); + okBt.Location = new Point(0, 120); + pk1.Location = new Point(100, 0); + + + + pk1.Image = imageSet; + + + form2.Controls.Add(cb1); + form2.Controls.Add(rb1); + form2.Controls.Add(rb2); + form2.Controls.Add(rb3); + form2.Controls.Add(okBt); + form2.Controls.Add(pk1); + + rb1.Checked = true; + cb1.Checked = true; + + okBt.Click += delegate (object sender, EventArgs args) + { + //해상도 설정 + + RegistryKey reg = Registry.CurrentUser; + reg = reg.OpenSubKey(@"Software\Phantagram\Shining Lore Online", true); + + if (rb1.Checked == true) + { + if (reg == null) + { + MessageBox.Show("error : 해상도를 설정할 수 없습니다."); + return; + } + else + { + reg.SetValue("Resolution", 800); + } + } + else if (rb2.Checked == true) + { + if (reg == null) + { + MessageBox.Show("error : 해상도를 설정할 수 없습니다."); + return; + } + else + { + reg.SetValue("Resolution", 1024); + } + } + else if (rb3.Checked == true) + { + if (reg == null) + { + MessageBox.Show("error : 해상도를 설정할 수 없습니다."); + return; + } + else + { + reg.SetValue("Resolution", 1152); + } + } + + //창모드 전체화면 설정 + if (cb1.Checked == true) + { + resolutionNum = 1; + } + else + { + resolutionNum = 0; + } + + //해상도 모드를 설정하면 설정값을 저장하도록 런처셋 파일을 생성한다. + System.IO.StreamWriter objSaveFile = new System.IO.StreamWriter(Application.StartupPath + @"\LauncherSet.txt"); + objSaveFile.WriteLine(resolutionNum); + objSaveFile.Close(); + + optionCheck = false; + form2.Close(); + }; + + form2.Show(); + + optionCheck = true; + } + + } +} diff --git a/ProcessControl.cs b/ProcessControl.cs new file mode 100644 index 0000000..f47737a --- /dev/null +++ b/ProcessControl.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Windows.Forms; + +/* +프로세스 리스트를 컨트롤 하는 클래스로 +다중 클라이언트 제어를 위한 기능 추가 예정 +1인 1클라이언트 혹은 1인 2클라이언트까지만 제어할 예정 + +게임 시작 버튼 입력 시 클라이언트 개수를 체크하여 실행 제한을 둔다. + +혹시 편법으로 클라이언트를 일정 개수 이상 실행할 경우도 염두하여 +프로세스 리스트를 5분 단위로 체크하여 일정 개수 이상의 클라이언트가 +실행 될 경우 모든 게임 종료. +*/ + +namespace ShiningLoreLauncher +{ + class ProcessControl + { + int count = 0; + + //모든 프로세스 리스트 검색 + public void ProcessCheckM(int numCheck) + { + Process[] pl = Process.GetProcesses(); + if (numCheck == 0) + { + foreach (Process p in pl) + { + WriteProcessInfo(p); + } + } + else if(numCheck == 1) + { + foreach (Process p in pl) + { + AllClose(p); + } + } + } + + //프로세스 리스트중에서 샤이닝로어 클라이언트 검출 + private void WriteProcessInfo(Process processInfo) + { + string processname = processInfo.ProcessName.ToString(); + if (processname == "SlOnline") + { + count++; + } + //만약에 샤로가 2개 넘어서 켜질 경우 + if (count > 2 && processname == "SlOnline") + { + processInfo.Kill(); + MessageBox.Show("클라이언트가 세개 이상입니다. 샤이닝로어를 강제 종료합니다."); + } + } + + public void AllClose(Process processInfo) + { + string processname = processInfo.ProcessName.ToString(); + if (processname == "SlOnline") + { + processInfo.Kill(); + MessageBox.Show("런처가 종료되었습니다. 모든 샤이닝로어를 종료합니다."); + } + } + } +} diff --git a/Start/StartGame.cs b/Start/StartGame.cs new file mode 100644 index 0000000..fa2fc8a --- /dev/null +++ b/Start/StartGame.cs @@ -0,0 +1,126 @@ +using ShiningLoreLauncher.Class; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Net; +using System.Text; +using System.Windows.Forms; + +/* +게임 시작 버튼 입력하였을 때 동작 처리 클래스 +cmd를 이용하여 게임을 실행한다. +*/ + +namespace ShiningLoreLauncher +{ + class StartGame + { + public static object MessgeBox { get; private set; } + + //해상도 값에 따른 세팅하며 게임 실행 함수 호출 + public static void resolution() + { + System.IO.StreamReader objReadFile; + objReadFile = new System.IO.StreamReader(Application.StartupPath + @"\LauncherSet.txt"); + ChangeDnsToIp cdt = new ChangeDnsToIp(); + + //런처셋txt 값 읽어와서 전체화면/창모드 실행 + switch (int.Parse((objReadFile.ReadLine().ToString()))) + { + case 0: + fullMode(cdt.ipAddressGet()); + break; + case 1: + winMode(cdt.ipAddressGet()); + break; + } + } + + //전체화면으로 게임 실행 + public static void fullMode(string ipAddressName) + { + ProcessStartInfo cmd = new ProcessStartInfo(); + Process process = new Process(); + + cmd.FileName = @"cmd"; + cmd.WindowStyle = ProcessWindowStyle.Hidden; + cmd.CreateNoWindow = true; + cmd.UseShellExecute = false; + cmd.RedirectStandardOutput = true; + cmd.RedirectStandardInput = true; + cmd.RedirectStandardError = true; + + process.EnableRaisingEvents = false; + process.StartInfo = cmd; + process.Start(); + + process.StandardInput.Write(@"start SlOnline.exe /updatecomplete: /gwip:" + ipAddressName + Environment.NewLine); + + process.WaitForExit(500); + /* + System.Diagnostics.Process ps = new System.Diagnostics.Process(); + + System.Diagnostics.Process.Start("cmd.exe", "/C SlOnline.exe" + " /updatecomplete: /gwip:" + ipAddressName); + + + System.Threading.Thread.Sleep(500); + Process[] p = Process.GetProcessesByName("cmd"); + if (p.GetLength(0) > 0) + { + p[0].Kill(); + } + */ + } + + //창모드로 게임 실행 + public static void winMode(string ipAddressName) + { + ProcessStartInfo cmd = new ProcessStartInfo(); + Process process = new Process(); + + cmd.FileName = @"cmd"; + cmd.WindowStyle = ProcessWindowStyle.Hidden; + cmd.CreateNoWindow = true; + cmd.UseShellExecute = false; + cmd.RedirectStandardOutput = true; + cmd.RedirectStandardInput = true; + cmd.RedirectStandardError = true; + + process.EnableRaisingEvents = false; + process.StartInfo = cmd; + process.Start(); + + process.StandardInput.Write(@"start SlOnline.exe /updatecomplete: /win/gwip:" + ipAddressName + Environment.NewLine); + + process.WaitForExit(500); + + /* + ProcessStartInfo cmd = new ProcessStartInfo(); + Process process = new Process(); + + cmd.FileName = @"SlOnline.exe /updatecomplete: /win/gwip:" + ipAddressName; + cmd.WindowStyle = ProcessWindowStyle.Hidden; + cmd.CreateNoWindow = true; + //cmd.UseShellExecute = false; + + //process.EnableRaisingEvents = false; + process.StartInfo = cmd; + process.Start(); + //process.StandardInput.Close(); + */ + /* + System.Diagnostics.Process.Start("cmd.exe", "/C SlOnline.exe" + " /updatecomplete: /win/gwip:" + ipAddressName); + + System.Threading.Thread.Sleep(500); + + Process[] p = Process.GetProcessesByName("cmd"); + if (p.GetLength(0) > 0) + { + p[0].Kill(); + } + */ + } + } +} diff --git a/UpdateFile.cs b/UpdateFile.cs new file mode 100644 index 0000000..5333475 --- /dev/null +++ b/UpdateFile.cs @@ -0,0 +1,169 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Text; +using System.Windows.Forms; + +namespace ShiningLoreLauncher.Class +{ + class UpdateFile + { + //메인 폼에 있는 텍스트라벨을 갱신하기 위해 델리게이트 사용 + public delegate void uptext(string upLabelText); + public event uptext ReturnToText; + + //메인 폼에 있는 버튼 제어 + public delegate void startBtnSet(bool set); + public event startBtnSet startBtnSetM; + + public delegate void optionBtnSet(bool set); + public event optionBtnSet optionBtnSetM; + + //파일 개수 확인 + int fileCount = 0; + + //파일 다운로드 메소드 + private void updateSet() + { + + MessageBox.Show("업데이트가 있습니다. 서버 상황에 따라 약 1~5분이 소요됩니다.\n확인버튼을 누르시면 업데이트를 시작합니다."); + + string[] sefileName = {"Budt.bin", "Dhs.bin", "Dkjsin.bin", "Ehdt.bin", "Ikdmn.bin", "Lkezmd.bin", + "Osa.bin" , "Qods.bin" , "SlOnline.exe", "ClientVersion.txt"}; + + string[] cefileName = { @"\Data\Budt.bin", @"\Data\Dhs.bin", @"\Data\Dkjsin.bin", @"\Data\Ehdt.bin", @"\Data\Ikdmn.bin", @"\Data\Lkezmd.bin", + @"\Data\Osa.bin" , @"\Data\Qods.bin" , @"\SlOnline.exe", @"\Data\ClientVersion.txt"}; + + for (int i = 0; i < sefileName.Length; i++) + { + //자동 업데이트 기능. 동적할당 + WebClient webFileDown = new WebClient(); + //서버에 있는 txt 파일을 읽어서 해시코드 호출한다. + + webFileDown.DownloadProgressChanged += new DownloadProgressChangedEventHandler(DownloadProgressCallback); + + webFileDown.DownloadFileAsync(new Uri(@"http://youid.iptime.org:9999/updateFile/" + sefileName[i]), Application.StartupPath + cefileName[i]); + + webFileDown.Dispose(); + + //ReturnToText("파일 다운로드중.. (" + (fileCount / 2) + "/" + "9)"); + } + } + + private void DownloadProgressCallback(object sender, DownloadProgressChangedEventArgs e) + { + // Displays the operation identifier, and the transfer progress. + string fileName = (string)e.UserState; + int Percentage = e.ProgressPercentage; // 비동기 작업의 진행을 나타내는 백분율 값입니다. + long TotalBytesToReceive = e.TotalBytesToReceive; // 다운받아야 할 데이터 길이입니다. + long BytesReceived = e.BytesReceived;// 현재까지 다운 받은 데이터 길이입니다. + + startBtnSetM(false); + optionBtnSetM(false); + + if (TotalBytesToReceive == BytesReceived) + { + fileCount += 1; + ReturnToText("파일 다운로드중.. (" + (fileCount / 2) + "/" + "10) "); + } + + if ((fileCount / 2) >= 10) + { + startBtnSetM(true); + optionBtnSetM(true); + //StartBtn.Enabled = true; + //Option.Enabled = true; + ReturnToText("업데이트 완료!"); + } + } + + + //버전 확인 메소드 + private void versionTextCheck() + { + String mainStr; + String bufStr; + + int mainInt; + int subInt; + //서버에 있는 버전 파일 내용을 읽어온다. + WebClient webFileRead = new WebClient(); + + //읽어온 파일의 내용을 잘라서 버퍼에 저장한다. + mainStr = webFileRead.DownloadString(new Uri(@"http://youid.iptime.org:9999/updateFile/ClientVersion.txt")).Substring(16); + + webFileRead.Dispose(); + + //파일 사이즈 검사 가끔 업데이트하다 종료할 경우 버전 파일이 다운안되서 사이즈가 0 일때를 대비함. + FileInfo fInfo = new FileInfo(Application.StartupPath + @"\Data\ClientVersion.txt"); + //파일 사이즈가 0일때 파일 생성하고 업데이트 체크 함수 호출 + if (fInfo.Length == 0) + { + System.IO.StreamWriter objSaveFile; + objSaveFile = new System.IO.StreamWriter(Application.StartupPath + @"\Data\ClientVersion.txt"); + objSaveFile.WriteLine("Client Vercion = 20150829"); + objSaveFile.Close(); + updateCheck(); + } + //버전 텍스트 파일 사이즈가 0이 아닐떄 + else + { + System.IO.StreamReader objReadFile; + //현재 폴더에 있는 버전 파일 읽어온다. + objReadFile = new System.IO.StreamReader(Application.StartupPath + @"\Data\ClientVersion.txt"); + + //읽어온 파일의 내용을 잘라서 버퍼에 저장한다. + bufStr = objReadFile.ReadLine().Substring(16); + + //자른 문자를 int형으로 형변환 한다. + mainInt = int.Parse(mainStr); + subInt = int.Parse(bufStr); + objReadFile.Close(); + + //비교 버전이 같지않으면 업데이트 실행 + if (mainInt != subInt) + { + updateSet(); + } + else + { + //ReturnToText("최신버전입니다."); + } + } + } + + //버전 확인 파일 유무 체크 및 파일 버전 체크 + public void updateCheck() + { + //버전 텍스트 파일이 있는지 확인하고 없으면 생성 있으면 바로 버전체크 + FileInfo fIlecheck = new FileInfo(Application.StartupPath + @"\Data\ClientVersion.txt"); + + string sDirPath; + sDirPath = Application.StartupPath + "\\Data"; + DirectoryInfo di = new DirectoryInfo(sDirPath); + + if (di.Exists == false) + { + di.Create(); + } + //파일이 있다면 + if (fIlecheck.Exists == true) + { + versionTextCheck(); + + } + //파일이 없다면 + else + { + System.IO.StreamWriter objSaveFile; + objSaveFile = new System.IO.StreamWriter(Application.StartupPath + @"\Data\ClientVersion.txt"); + objSaveFile.WriteLine("Client Vercion = 20150829"); + objSaveFile.Close(); + updateCheck(); + } + //System.IO.StreamWriter objSaveFile = new System.IO.StreamWriter(@"version.txt"); + } + } +}