private static string downloadUpdateFile(string dirName, string update, string name, string version, string[] args) { var r = new response(); var url = "http://" + (update + "/update/" + name + "-" + version + ".updt").Replace("//", "/"); var savePath = Path.Combine(dirName, name + "-" + version + ".updt"); var fi = new FileInfo(savePath); if (fi.Exists) { toUpdateLog("target file always downloaded"); if ( DateTime.Now.ToFileTime() - fi.CreationTime.ToFileTime() < 24 * (3600L * 1000 * 10000) ) { if (fi.Length == 0) { toUpdateLog("update is cancelled: file already loaded and applied - " + savePath); // File.AppendAllText(errorFileName, String.Format(errorMessage, DateTime.Now, "Данный файл уже закачан", savePath)); return(""); } else { toUpdateLog("update: file already loaded, but not applied - " + savePath); return(savePath); } } else { toUpdateLog("early downloaded file to delete"); File.Delete(savePath); toUpdateLog("early downloaded file deleted"); } } deleteOldUpdtFiles(dirName, name, savePath); toUpdateLog("try to get file from url " + url); byte[] file = null; int countOfTryes = 0; bool loaded = false; do { try { countOfTryes++; file = r.getFile(url, null); loaded = file != null; if (!loaded) { stopEvent.WaitOne(7148); } } catch (Exception e) { toUpdateLog("get file return null - update failure. Error message " + e.Message + "\r\n" + e.StackTrace); if (countOfTryes > 3 || stopEvent.WaitOne(7148)) // ждём 7,148 секунд { return(null); } } }while (!loaded && countOfTryes < 4); if (file == null) { toUpdateLog("get file return null - update failure"); return(null); } toUpdateLog("" + file.Length + " bytes getted from url " + url); // :$$$.проверкаПодлинности\ :проверкаПодлинности :безопасность using (var ms = new MemoryStream(file)) { var totalSize = readInt(ms); if (totalSize != file.Length) { File.AppendAllText(errorFileName, String.Format(errorMessage, DateTime.Now, "Файл имеет неверный формат: размер файла не совпадает с заявленным", "Отсутствует / downloadUpdateFile")); MessageBox.Show("Файл обновления, полученный с '" + url + "' имеет неверный формат.", "Ошибка обновления", MessageBoxButtons.OK, MessageBoxIcon.Error); return(null); } var headersSize = readInt(ms); var size = readInt(ms); var headSignature = Encoding.UTF8.GetBytes("\r\nFDSC PACK / prg.8vs.ru\r\n"); if (headSignature.Length != size) { File.AppendAllText(errorFileName, String.Format(errorMessage, DateTime.Now, "Файл имеет неверный формат: размер сигнатуры не совпадает с заявленным", "Отсутствует / downloadUpdateFile")); MessageBox.Show("Файл обновления, полученный с '" + url + "' имеет неверный формат.", "Ошибка обновления", MessageBoxButtons.OK, MessageBoxIcon.Error); return(null); } var b = readArray(ms, headSignature.Length); if (!checkArray(headSignature, b)) { File.AppendAllText(errorFileName, String.Format(errorMessage, DateTime.Now, "Файл имеет неверный формат: неверная сигнатура типа файла", "Отсутствует / downloadUpdateFile")); MessageBox.Show("Файл обновления, полученный с '" + url + "' имеет неверный формат.", "Ошибка обновления", MessageBoxButtons.OK, MessageBoxIcon.Error); return(null); } size = readInt(ms); // Длинна имени ключа var keyNameBlob = readArray(ms, size); var keyName = Encoding.GetEncoding("windows-1251").GetString(keyNameBlob); size = readInt(ms); // подпись sha512 var shas = readArray(ms, size); size = readInt(ms); // подпись md5 var md5s = readArray(ms, size); if (headersSize != ms.Position - 8) { File.AppendAllText(errorFileName, String.Format(errorMessage, DateTime.Now, "Файл имеет неверный формат: размер заголовков не совпадает с заявленным", "Отсутствует / downloadUpdateFile")); MessageBox.Show("Файл обновления, полученный с '" + url + "' имеет неверный формат.", "Ошибка обновления", MessageBoxButtons.OK, MessageBoxIcon.Error); return(null); } var packetSize = readInt(ms); if (totalSize - ms.Position != packetSize) { File.AppendAllText(errorFileName, String.Format(errorMessage, DateTime.Now, "Файл имеет неверный формат: размер пакета не совпадает с заявленным", "Отсутствует / downloadUpdateFile")); MessageBox.Show("Файл обновления, полученный с '" + url + "' имеет неверный формат.", "Ошибка обновления", MessageBoxButtons.OK, MessageBoxIcon.Error); return(null); } var packet = readArray(ms, packetSize); var keyFileName = keyName + ".pub"; if (!File.Exists(keyFileName)) { File.AppendAllText(errorFileName, String.Format(errorMessage, DateTime.Now, "Файл, полученный с " + url + ", имеет неизвестный ключ подписи: это может быть следствием ошибки обновления или атаки со стороны третьих лиц", keyFileName)); MessageBox.Show("Файл, полученный с " + url + ", имеет неизвестный ключ подписи: это может быть следствием ошибки обновления или атаки со стороны третьих лиц", "Ошибка обновления", MessageBoxButtons.OK, MessageBoxIcon.Error); return(null); } using (CngKey DSKey = CngKey.Import(File.ReadAllBytes(keyFileName), CngKeyBlobFormat.EccPublicBlob)) { using (var ecdsa = new ECDsaCng(DSKey)) { ecdsa.HashAlgorithm = CngAlgorithm.Sha512; if (!ecdsa.VerifyData(packet, shas)) { File.AppendAllText(errorFileName, String.Format(errorMessage, DateTime.Now, "Файл имеет неверный формат: подпись sha512 не подлинная. Это может быть ошибка обновления или неуспешная попытка атаки на обновляемый компьютер со стороны третьих лиц", "Отсутствует / downloadUpdateFile")); MessageBox.Show("Файл обновления, полученный с '" + url + "' имеет подпись sha512, которая не прошла проверку подлинности. Это может быть ошибка обновления или неуспешная попытка атаки на обновляемый компьютер со стороны третьих лиц", "Ошибка обновления", MessageBoxButtons.OK, MessageBoxIcon.Error); return(null); } ecdsa.HashAlgorithm = CngAlgorithm.MD5; if (!ecdsa.VerifyData(packet, md5s)) { File.AppendAllText(errorFileName, String.Format(errorMessage, DateTime.Now, "Файл имеет неверный формат: подпись md5 не подлинная. Это может быть ошибка обновления или неуспешная попытка атаки на обновляемый компьютер со стороны третьих лиц", "Отсутствует / downloadUpdateFile")); MessageBox.Show("Файл обновления, полученный с '" + url + "' имеет подпись md5, которая не прошла проверку подлинности. Это может быть ошибка обновления или неуспешная попытка атаки на обновляемый компьютер со стороны третьих лиц", "Ошибка обновления", MessageBoxButtons.OK, MessageBoxIcon.Error); return(null); } } } } toUpdateLog("get and verify file - success"); File.WriteAllBytes(savePath, file); new FileInfo(savePath).CreationTime = DateTime.Now; toUpdateLog(String.Format("save file to '{0}' - success", savePath)); return(savePath); }
static int Main(string[] args) { AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); Directory.SetCurrentDirectory(Path.GetDirectoryName(Application.ExecutablePath)); toUpdateLog("started\r\n" + stringArrayToLogString(args, "\t")); if (!s.WaitOne(0)) { Console.WriteLine("semaphore locked to umove.exe; exited"); toUpdateLog("semaphore locked to umove.exe; exited"); return(3); } var umove = false; try { argsString = getArgumentsFromArgArray(args); if (args.Length == 1 && args[0] == "-umove") { var result = umoveRename(); toUpdateLog("-umove"); umove = true; } else { umoveRename(); } if (args.Length == 1 && args[0] == "-v") { AllocConsole(); Console.WriteLine(version); Console.ReadKey(); FreeConsole(); return(0); } createOrParseIni(); var uuPath = downloadUpdate(Directory.GetCurrentDirectory(), opts["updatorDir", ""].Replace("$$$", "update"), "update", version, args); if (!String.IsNullOrEmpty(uuPath)) { try { File.WriteAllText("uup.flag", Path.GetFullPath(uuPath) + "\r\n"); Process.Start("umove.exe", "uup.flag \"vs8.ru updator semaphore\" 50 \"\""); } catch (Exception e) { toUpdateLog(e.Message + "\r\n" + e.StackTrace); } } if (umove) { return(51); } if ( args.Length > 3 || args.Length < 3 || (args.Length == 1 && (args[0] == "-?" || args[0] == "/?" || args[0] == "/help" || args[0].ToLower() == "--help")) ) { AllocConsole(); Console.WriteLine("updatorvs8.exe updateName version path_to_dwnl"); Console.WriteLine("for example: updatorvs8.exe relaxtime 20110929 D:/rtbd/"); Console.WriteLine("warning: umove.exe must be place to same directory updatorvs8.exe"); Console.ReadKey(); FreeConsole(); return(1); } var dirName = args[2]; if (!Directory.Exists(dirName)) { Console.WriteLine(String.Format("update directory '{0}' is not exists", args[1])); return(2); } var updateFlagFile = Path.Combine(new string[] { dirName, "update.flag" }); File.Delete(updateFlagFile); var updatedPath = downloadUpdate(dirName, opts["updateDir", ""].Replace("$$$", args[0]), args[0], args[1], args); var updated = !String.IsNullOrEmpty(updatedPath); if (updated) { File.WriteAllText(updateFlagFile, Path.GetFullPath(updatedPath) + "\r\n"); Console.WriteLine("success"); toUpdateLog("success"); if (args[0] == "relaxtime") { try { var resp = new response(); resp.getFile("http://mc.yandex.ru/watch/15915832", @"http://relaxtime.8vs.ru/success.html?guid=" + opts["updatorGUID"]); } catch (Exception e) { toUpdateLog("success and error: " + e.Message); } } } else { if (updatedPath == null) { Console.WriteLine("failure"); toUpdateLog("failure"); if (args[0] == "relaxtime") { try { var resp = new response(); resp.getFile("http://mc.yandex.ru/watch/15915832", @"http://relaxtime.8vs.ru/failure.html?guid=" + opts["updatorGUID"]); } catch (Exception e) { toUpdateLog("failure and error: " + e.Message); } } } else { Console.WriteLine("neutral"); toUpdateLog("neutral"); if (args[0] == "relaxtime") { try { var resp = new response(); resp.getFile("http://mc.yandex.ru/watch/15915832", @"http://relaxtime.8vs.ru/neutral.html?guid=" + opts["updatorGUID"]); } catch (Exception e) { toUpdateLog("neutral and error: " + e.Message); } } } } toUpdateLog("ended"); var fi = new FileInfo(updatorLogFileName); truncateLog(fi); if (updated) { return(0); } else { return(11); } } finally { s.Release(); s.Close(); } }