Ноя 04, 2015
Дано: Навигационный терминал Fort-112 3g от пермской компании Fort Telecom.
Задача: минимум - узнать явки и пароли, максимум - получить полное управление коробкой.
Погнали.
Как всегда, идём на сайт производителя, вникаем в мануалы. Понимаем, что одними смсками мы коробку не победим; она привязана к списку телефонных номеров и, мало того, хочет знать пароли. В этом месте производителю зачёт!:)
Ок... Для конфигурации устройства нам нужна некая софтина под кодовым названием «Конфигуратор». Здесь ждёт небольшой сюрприз. Если «Конфигуратор» можно найти на просторах интернета, то с драйверами явная проблема. Хорошо, просим софт у производителя... Ииии... в России есть странная особенность - у нас очень любят выпустить недопродукт, а-ля конструктор, накрутить поверх страшнючее ПО и никому ничего не давать:) Исключение, пожалуй, Александр Ерасов.
Александр Евгеньичу пламенный привет:) А мы продолжим.
Я не зря упомянул про конструктор... Смотрим на чём собран прибор - до боли знакомый сто пиновый микроконтроллер STM32F4 от швейцарской компании STMicroelectronics. Это значит, что прошивка коробки практически у нас в руках.
Для начала, конечно же, читаем даташит, смотрим распиновку, находим ногу BOOT0, смотрим куда распаяна.
Ставим джампер в этом месте...
Теперь наша коробка будет стартовать в Device Firmware Update Mode (больше, чем на 5 сек.) с доступом ко всем разделам памяти.
Отлично, дальше нужно скачать пакет программ DfuSe c сайта st.com. Устанавливаем. Запускаем DFUSE Demo. Втыкаем коробку в USB порт. Подаём питание. Смотрим, что получилось.
Шикарно!:) Смотрим права на Internal Flash, именно эта часть памяти нам понадобится.
Полный доступ по всем фронтам. Это радует:) В секции Upload Action выбираем место, куда сохранять дамп памяти, жмём кнопарь Upload.
На выходе получаем файл с раширением .dfu... Запускаем программу DFU File Manager, делаем из .dfu multi BIN file (это важно, если править .dfu напрямую, будет много матюгов на CRC файла при обратных действиях) и открываем в HEX редакторе.
Собственно, вот оно. Довольно много интересного для зоркого взгляда американского наблюдателя.
Заливка исправленной прошивки происходит ровно таким же образом, но наоборот... с небольшим финтом ушами:)
С этой коробкой пока всё. Ещё три на подходе:))))
upd 28.04.2017:
FORT Monitor
FORT-112 All
ГЛОНАСС
Окт 08, 2015
Расшифрованная и, чтобы не делала killout всем подряд, немного подхаченная процедура dbo.clcsp_MainCalculator3 из БД TRANSNAVI - Автоматизированная Система Учёта Транспортной Работы, НПП «Транснавигация».
USE [TRANSNAVI]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: Dmitriy Def
-- Create date: 24.09.2015
-- Description: Encrypt
-- =============================================
--ОСНОВНАЯ ПРОЦЕДУРА ЯДРА
ALTER PROCEDURE [dbo].[clcsp_MainCalculator3Hack]
AS
set nocount on
--временная таблица
create table #NRD(NRD_Identificator int)
declare @CurDate datetime
declare @CurInt int
declare @OldInt int
declare @ServiceDay int
set @ServiceDay=0
--Вносим строчку в журнал
insert into Logs values(GetDate(),'ЗАПУСК СЛУЖБЫ',0)
set @OldInt=-1
-------------------------------------------------------------------------------------------------------------------------
--ОСНОВНОЙ ЦИКЛ
-------------------------------------------------------------------------------------------------------------------------
StartService:
--читаем основные параметры
declare @enable_BDI bit
set @enable_BDI=case when dbo.fn_GetParam('enable_BDI','0')='1' then 1 else 0 end
declare @enable_kernel bit
set @enable_kernel=case when dbo.fn_GetParam('enable_kernel','1')='1' then 1 else 0 end
declare @enable_digithandle bit
set @enable_digithandle=case when dbo.fn_GetParam('enable_digithandle','0')='1' then 1 else 0 end
declare @enable_failwindow bit
set @enable_failwindow=case when dbo.fn_GetParam('enable_failwindow','1')='1' then 1 else 0 end
declare @enable_hotwindow bit
set @enable_hotwindow=case when dbo.fn_GetParam('enable_hotwindow','1')='1' then 1 else 0 end
declare @enable_kkphandle bit
set @enable_kkphandle=case when dbo.fn_GetParam('enable_kkphandle','1')='1' then 1 else 0 end
declare @enable_nariadcross bit
set @enable_nariadcross=case when dbo.fn_GetParam('enable_nariadcross','1')='1' then 1 else 0 end
declare @enable_navhandle bit
set @enable_navhandle=case when dbo.fn_GetParam('enable_navhandle','1')='1' then 1 else 0 end
declare @enable_rasphandle bit
set @enable_rasphandle=case when dbo.fn_GetParam('enable_rasphandle','1')='1' then 1 else 0 end
declare @enable_tablohandle bit
set @enable_tablohandle=case when dbo.fn_GetParam('enable_tablohandle','0')='1' then 1 else 0 end
--определяем сколько раз в минуту запускать обработчик
declare @startperminute int
set @startperminute=cast(dbo.fn_GetParam('clc_startperminute','4') as int)
declare @startonmin int
if (@startperminute>0) and (@startperminute<=60)
set @startonmin=60/@startperminute
else
set @startonmin=15
declare @failkeep int
set @failkeep=cast(dbo.fn_GetParam('clc_failkeep','7') as int)
declare @handlegraphdelta int
set @handlegraphdelta=cast(dbo.fn_GetParam('clc_handlegraphdelta','30') as int)
--если не разрешают запускать ядро, то выходим
if @enable_kernel=0 return(0)
--ждем время запуска службы
set @CurDate=GetDate()
set @CurInt=DatePart(hour,@CurDate)*3600+DatePart(minute,@CurDate)*60+DatePart(second,@CurDate)
while (@CurInt % @startonmin<>0) or (@CurInt=@OldInt)
begin
waitfor delay '00:00:01'
set @CurDate=GetDate()
set @CurInt=DatePart(hour,@CurDate)*3600+DatePart(minute,@CurDate)*60+DatePart(second,@CurDate)
end
set @OldInt=@CurInt
--Определяем дату наряда
declare @NariadDate datetime
declare @ND_Identificator int
declare @CurTime int
set @NariadDate=@CurDate
set @CurTime=DatePart(hour,@NariadDate)*60+DatePart(minute,@NariadDate)-180
set @NariadDate=Cast(Floor(Cast(@NariadDate as float))as datetime)
if @CurTime<0
begin
set @CurTime=1440+@CurTime
set @NariadDate=DATEADD(day,-1,@NariadDate)
end
set @ND_Identificator=dbo.fn_GetNariadIndex(@NariadDate)
--Если время по чисам системы 3:00, то выполняем ряд процедур по инициализации следующего дня
if @CurInt between 10800 and 10860
begin
if DatePart(day,@CurDate)<>@ServiceDay
begin
set @ServiceDay=DatePart(day,@CurDate)
--Очищаем оперативную навиацию
truncate table Nav
--Очищаем таблицу
truncate table Nav_cur
--Очищаем LOG
truncate table Logs
--очищаем рабочую таблицу связок
truncate table NRDCPLink
--Очищаем файл паркового опроса
if dbo.fn_TableExists('tbParkOpros')=1 truncate table tbParkOpros
--Очищаем отметки по ККП
if dbo.fn_TableExists('tbFreeNav')=1 truncate table tbFreeNav
--Очищаем пересечения наряда
if dbo.fn_TableExists('tbNariadInfo')=1 delete from tbNariadInfo where ND_Identificator<@ND_Identificator-@failkeep
--очищаем горячее окно
if dbo.fn_TableExists('tbErrorLog')=1 delete from tbErrorLog where ND_Identificator<@ND_Identificator-@failkeep
--очищаем окно нарушений
delete from tbMainWindow where ND_Identificator<@ND_Identificator-@failkeep
truncate table tbMainWindow_cur
--Очищаем оперативную цифровую модель
if dbo.fn_TableExists('tbDigitPos')=1 truncate table tbDigitPos
--обрабатываем новые мониторинговые таблицы
insert into jobs (ND_Identificator,NRD_Identificator,JB_MinCalcTime,JB_MaxCalcTime,JB_MinCalcOrder,JB_MaxCalcOrder,JB_Command,NSIT_UniqueID)
select ND_Identificator,NRD_Identificator,0,1439,-10000,1000000,1,NSIT_UniqueID
from tbBaseNariad where ND_Identificator=@ND_Identificator
end
end
--блок криптографической проверки
if (@CurInt % 3600)=0
begin
declare @bad bit
declare @alv_res int
declare @spid smallint
declare @spid_str varchar(15)
set @bad=0
if not exists(select * from TRANSNAVI.dbo.sysobjects where name='crysp_alv' and xtype='P') or
not exists(select * from TRANSNAVI.dbo.sysobjects where name='crysp_dcb' and xtype='P') or
not exists(select * from TRANSNAVI.dbo.sysobjects where name='crysp_dcl' and xtype='P') or
not exists(select * from TRANSNAVI.dbo.sysobjects where name='crysp_gm' and xtype='P') or
not exists(select * from TRANSNAVI.dbo.sysobjects where name='cryfn_gsn' and xtype='FN') set @bad=1
else begin
exec @alv_res=dbo.crysp_alv 255
if @alv_res<0 set @bad=0
end
if @bad=1
begin
--всех убить
declare killcur cursor
local
for
select spid from master.dbo.sysprocesses sp
inner join master.dbo.sysdatabases db on sp.dbid=db.dbid
where db.name='TRANSNAVI' and spid<>@@spid
open killcur
fetch next from killcur into @spid
while @@fetch_status=0
begin
set @spid_str=cast(@spid as varchar)
exec ('KILL '+@spid_str)
fetch next from killcur into @spid
end
close killcur
deallocate killcur
--и выйти
return(-1);
end;
end
--если это первый вызов минуты, то набираем задание
if (@CurInt % 60)=0
begin
--очищаем таблицу
truncate table #NRD
--заполняем ее новыми значениями
insert into #NRD(NRD_Identificator)
select NRD_Identificator from tbBaseNariad
where (ND_Identificator=@ND_Identificator) and (NSIT_UniqueID>0) and
(NRD_ExitPark-@handlegraphdelta<=@CurTime and @CurTime<=NRD_EnterPark+@handlegraphdelta)
--Очищаем окно нарушений от старых данных (которых нет в задании)
delete from tbMainWindow_cur where not exists(select top 1 * from #NRD where tbMainWindow_cur.NRD_Identificator=#NRD.NRD_Identificator)
end
--Вносим строчку в журнал
insert into Logs values(GetDate(),'ВЫЗОВ',0)
--Проверяем скорость поступления данных
declare @CountBefore int
declare @CountAfter int
declare @MaxInsSpeed int
set @MaxInsSpeed=cast(dbo.fn_GetParam('clc_maxinsspeed','10') as int)
set @CountBefore=(select count(*) from Nav_buf)
waitfor delay '00:00:01'
set @CountAfter=(select count(*) from Nav_buf)
if @CountAfter-@CountBefore>@MaxInsSpeed
begin
insert into Logs values(GetDate(),'ВЫЗОВ ОТМЕНЕН',0)
goto StartService
end
--Обновляем таблицу связанных КП
delete from NRDCPLink
where
not exists
(
select top 1 * from tbBaseNariad
where NRDCPLink.NRD_Identificator=tbBaseNariad.NRD_Identificator
)
insert into NRDCPLink(ND_Identificator,NRD_Identificator,NSIT_UniqueID,CP_Identificator,CNRD_EndStation)
select distinct BN.ND_Identificator,BN.NRD_Identificator,BN.NSIT_UniqueID,CN.CP_Identificator,CN.CNRD_EndStation
from tbBaseNariad BN inner join tbCardNariad CN on BN.NRD_Identificator=CN.NRD_Identificator
where not exists
(
select top 1 * from NRDCPLink
where NRDCPLink.NRD_Identificator=BN.NRD_Identificator
)
--Этап 0. Цифровая модель
if (@enable_digithandle=1)
begin
insert into
Logs values(GetDate(),'Начало цифровой модели',0)
exec dgtsp_CalcNavPosition @ND_Identificator
insert into Logs values(GetDate(),'Конец цифровой модели',0)
end
--Этап 1. Окапывание
declare @NRD_identificator int
declare @JobCount int
declare @JB_identificator uniqueidentifier
declare @JB_MinCalcTime int
declare @JB_MaxCalcTime int
declare @JB_MinCalcOrder int
declare @JB_MaxCalcOrder int
declare @JB_Command int
declare @NSIT_UniqueID int
declare @RowCount int
declare @RowResult int
set @RowCount=cast(dbo.fn_GetParam('clc_rowcount','10000') as int)
declare @MaxRestToCalc int
set @MaxRestToCalc=cast(dbo.fn_GetParam('clc_maxresttocalc','300') as int)
declare @BufCount int
set @BufCount=(select count(*) from nav_buf)
if (@enable_navhandle=1)
begin
insert into Logs values(GetDate(),'Начало Окапывания',@BufCount)
exec clcsp_LinkCurNavToCP3 @RowCount,@RowResult output
insert into Logs values(GetDate(),'Конец Окапывания',@BufCount)
if @RowResult>@MaxRestToCalc
begin
goto StartService
end
end
--Этап 2. Обработка
exec clcsp_GetCalcCur3
set @JobCount=(select count(*) from Jobs)
insert into Logs values(GetDate(),'Начало Обработки',@JobCount)
declare JobCur cursor
local
for select JB_Identificator,ND_Identificator,NRD_Identificator,JB_MinCalcTime,JB_MaxCalcTime,JB_MinCalcOrder,JB_MaxCalcOrder,JB_Command,NSIT_UniqueID
from Jobs
open JobCur
fetch next from JobCur into
@JB_Identificator,@ND_Identificator,@NRD_Identificator,@JB_MinCalcTime,@JB_MaxCalcTime,@JB_MinCalcOrder,@JB_MaxCalcOrder,@JB_Command,@NSIT_UniqueID
while @@fetch_status=0
begin
--пересчитываем график
if (@enable_rasphandle=1) exec clcsp_Calc3 @ND_Identificator,@NRD_Identificator,@JB_MinCalcOrder,@JB_MaxCalcOrder
--пересчитываем окно нарушений
if (@enable_failwindow=1) exec dspsp_MainWindow @NRD_Identificator
--пересчитываем горячее окно
if (@enable_hotwindow=1) exec dspsp_HotWindow @NRD_Identificator
--пересчитываем приезд отъезд от конечных
if (@JB_Command & 2)<>0
begin
if (@enable_kkphandle=1) exec dspsp_CalcFreeNav2 @NSIT_UniqueID
end
--вычисляем основные параметры графика (раз в минуту)(кол-во рейсов по плану)
exec dspsp_CalcGraph_minute @ND_Identificator,@NRD_Identificator,@CurTime
--расчитываем данные для БДИ
if (@enable_BDI=1) exec msgsp_FormRasp @NSIT_UniqueID,0
--удаляем график из задания
delete from #NRD where NRD_Identificator=@NRD_Identificator
--удаляем выполненное задание
delete from Jobs where JB_Identificator=@JB_Identificator
--переходим к следующему заданию
fetch next from JobCur into
@JB_Identificator,@ND_Identificator,@NRD_Identificator,@JB_MinCalcTime,@JB_MaxCalcTime,@JB_MinCalcOrder,@JB_MaxCalcOrder,@JB_Command,@NSIT_UniqueID
end
close JobCur
deallocate JobCur
insert into Logs values(GetDate(),'Конец Обработки',@JobCount)
--если это последний вызов минуты, то отрабатываем оставшиеся графики
if (@CurInt % 60)+@startonmin>=60
begin
set @JobCount=(select count(*) from #NRD)
insert into Logs values(GetDate(),'Начало Оперы',@JobCount)
declare cur cursor
local
for
select NRD_Identificator from #NRD
open cur
fetch next from cur into @NRD_Identificator
while @@fetch_status=0
begin
declare @leftlim int
declare @rightlim int
--перекрашиваем график
if (@enable_rasphandle=1)
begin
exec clcsp_CalcCurLimits @NRD_Identificator, @CurTime, @CurTime, 3, @leftlim OUTPUT , @rightlim OUTPUT
exec clcsp_ColorGraph3 @ND_Identificator,@NRD_Identificator,@leftlim,@rightlim,1
end
--пересчитываем окно нарушений
if (@enable_failwindow=1) exec dspsp_MainWindow @NRD_Identificator
--пересчитываем горячее окно
if (@enable_hotwindow=1) exec dspsp_HotWindow @NRD_Identificator
--вычисляем основные параметры графика (раз в минуту)
exec dspsp_CalcGraph_minute @ND_Identificator,@NRD_Identificator,@CurTime
--переходим к следующему графику
fetch next from cur into @NRD_Identificator
end
close
cur
deallocate cur
insert into Logs values(GetDate(),'Конец Оперы',@JobCount)
end
--расчет данных для табло
if (@enable_tablohandle=1)
begin
insert into Logs values(GetDate(),'Начало табло',0)
exec tblsp_CalculateTablo
insert into Logs values(GetDate(),'Конец табло',0)
end
goto StartService
ГЛОНАСС
Окт 08, 2015
За дверью
Начал я тут было писать продолжение истории, потом плюнул и запил мега сервис. Прям, регистрируешься, выбираешь навигатор/протокол, строишь маршрут, жмёшь кнопку пуск, и оно ездит по удалённым экранам «радаров», как настоящее. Главное, железные навигаторы обесточить, чтобы без палева:)
Чуть-чуть потестим и запустим в массы...
ГЛОНАСС
Окт 08, 2015
Так, это надо не забыть:) А то Дима весь мозг сломал: Почему в El Capitan-е не получается таскать окна и выделять текст, елозя тремя пальцами по трекпаду?
Step 1: Open System Preferences
Step 2: Click Accessibility
Step 3: Click Mouse & Trackpad
Step 4: Click Trackpad Options…
Step 5: Click Enable dragging
Step 6: Select “three finger drag” in the drop down box
Извращенцы!:)
Apple
Июл 24, 2015
В первой части мы разобрались, как работает пробный период системы. Ok, продолжим тянуть одеяло на себя.
Задача: изменить дату окончания пробного периода.
Погнали!
Смотрим, как дешифруются даты в файле ...modules/main/include.php:
$_1986987364 = COption::GetOptionString("main", "admin_passwordh");
while ($_1986987364) {
$_461848715 = base64_decode($_1986987364);
$_658498780 = "";
$_2139208883 = "thRH4u67fhw87V7Hyr12Hwy0rFr";
$_1215634966 = strlen($_2139208883);
$_278722441 = 0;
for ($_307887909 = 0; $_307887909 < strlen($_461848715); $_307887909++) {
$_658498780 .= chr(ord($_461848715[$_307887909]) ^ ord($_2139208883[$_278722441]));
if ($_278722441 == $_1215634966 - 1)
$_278722441 = 0;
else
$_278722441 = $_278722441 + 1;
}
//SITEEXPIREDATE
$_912457331 = mktime(0, 0, 0, intval($_658498780[6] . $_658498780[3]), intval($_658498780[1] . $_658498780[14]), intval($_658498780[10] . $_658498780[18] . $_658498780[7] . $_658498780[12]));
unset($_2139208883);
break;
}
@include($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/admin/define.php");
while (defined("TEMPORARY_CACHE")) {
$_1494959871 = base64_decode(constant("TEMPORARY_CACHE"));
$_464054490 = "";
$_527681262 = "DO_NOT_STEAL_OUR_BUS";
$_278722441 = 0;
for ($_307887909 = 0; $_307887909 < strlen($_1494959871); $_307887909++) {
$_464054490 .= chr(ord($_1494959871[$_307887909]) ^ ord($_527681262[$_278722441]));
if ($_278722441 == 19)
$_278722441 = 0;
else
$_278722441 = $_278722441 + 1;
}
//OLDSITEEXPIREDATE
$_1749264640 = mktime(0, 0, 0, intval($_464054490[6] . $_464054490[16]), intval($_464054490[9] . $_464054490[2]), intval($_464054490[12] . $_464054490[7] . $_464054490[14] . $_464054490[3]));
unset($_527681262);
break;
}
Берётся значение, декодируется из base64, прогоняется через XOR, из результата выдираются отдельные символы и формируется юникс тайм... Вся прелесть XOR шифрования в том, что для получения исходника достаточно прогнать зашифрованные данные через тот же цикл с тем же ключом.
Отлично.
Напишем универсальную функцию и скормим ей +30 дней от текущей даты.
<?php
function BitrixExpireDate($date, $key){
$outCode = '';
$x = 0;
for ($i = 0; $i < strlen($date); $i++) {
$outCode .= chr(ord($date[$i]) ^ ord($key[$x]));
if ($x == strlen($key) - 1)
$x = 0;
else
$x = $x + 1;
}
return $outCode;
}
$key1 = 'DO_NOT_STEAL_OUR_BUS+'; // OLDSITEEXPIREDATE
$key2 = 'thRH4u67fhw87V7Hyr12Hwy0rFr+'; // SITEEXPIREDATE
$nowDate = date('mdY', time() + 60*60*24*30); // сегодня 07242015
$codeDate1 = 'XX'.$nowDate[3].$nowDate[7].'XX'.$nowDate[0].$nowDate[5].'X'.$nowDate[2].'XX'.$nowDate[4].'X'.$nowDate[6].'X'.$nowDate[1].'X'; // OLDSITEEXPIREDATE
$codeDate2 = 'X'.$nowDate[2].'X'.$nowDate[1].'XX'.$nowDate[0].$nowDate[6].'XX'.$nowDate[4].'X'.$nowDate[7].'X'.$nowDate[3].'XXX'.$nowDate[5]; // SITEEXPIREDATE
echo $outCode1 = base64_encode(BitrixExpireDate($codeDate1, $key1)); // OLDSITEEXPIREDATE
echo '<br>';
echo $outCode2 = base64_encode(BitrixExpireDate($codeDate2, $key2)); // SITEEXPIREDATE
?>
Запускаем, получаем результат.
HBdsexcMb2MMdxkUbRdkCmca
LFoKcGwtBgY+MEVgAg4EECEqAQ==
Шикарно!:) Меняем значения в файле ...modules/main/admin/define.php и в строке admin_passwordh (таблица b_option), чистим ...managed_cache/, смотрим, что получилось.
Работает!
Дальше, думаю, понятно. Допиливаем скрипт, ложим на сервер, дёргаем кроном раз в сутки - вечные 30 дней триала и никаких модификаций ядра:)
Хак