diff --git a/docs/changes.txt b/docs/changes.txt index 4c19bc0..374a5ba 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -233,3 +233,6 @@ winws2: fixed lost windivert deinit on logical network disappear nfqws2: handling of incoming fragmented packets (no reconstruct, raw ip payload) zapret-auto: per_instance_condition orchestrator +zapret-auto: "instances" argument in condition orchestrator +zapret-auto: cond_tcp_has_ts, cond_lua iff functions +zapret-lib: replay_execution_plan and plan_clear max parameter diff --git a/docs/manual.en.md b/docs/manual.en.md index 30d0c6d..7f863e1 100644 --- a/docs/manual.en.md +++ b/docs/manual.en.md @@ -226,6 +226,7 @@ - [cond_random](#cond_random) - [cond_payload_str](#cond_payload_str) - [cond_tcp_has_ts](#cond_tcp_has_ts) + - [cond_lua](#cond_lua) - [Auxiliary programs](#auxiliary-programs) - [ip2net](#ip2net) - [mdig](#mdig) @@ -3568,10 +3569,10 @@ Retrieves, removes, and returns the first element of the [execution plan](#execu ### plan_clear ``` -function plan_clear(desync) +function plan_clear(desync, max) ``` -Clears the [execution plan](#execution_plan) in `desync.plan` by removing all `instance` elements. +Clears up to the "max" instances if "max" is defined or the whole [execution plan](#execution_plan) in `desync.plan`. ### orchestrate @@ -3585,10 +3586,10 @@ If `ctx=nil`, it does nothing, assuming the plan is already in `desync.plan`. ### replay_execution_plan ``` -function replay_execution_plan(desync) +function replay_execution_plan(desync, max) ``` -Executes the entire [execution plan](#execution_plan) from `desync.plan`, respecting the [instance cutoff](#instance_cutoff) and standard [payload](#in-profile-filters) and [range](#in-profile-filters) filters. +Executes up to the "max" instances if "max" is defined, or the entire [execution plan](#execution_plan) from `desync.plan`, respecting the [instance cutoff](#instance_cutoff) and standard [payload](#in-profile-filters) and [range](#in-profile-filters) filters. # zapret-antidpi.lua DPI attack program library @@ -4386,6 +4387,7 @@ function condition(ctx, desync) - arg: `iff` - name of the [iff function](#iff-functions) - arg: `neg` - invert the `iff` value; defaults to `false` +- arg: `instances` - how many following instances to execute conditionally. all if not defined. `condition` calls `iff`. If `iff xor neg = true`, all instances in the `plan` are executed; otherwise, the plan is cleared. @@ -4395,6 +4397,8 @@ function condition(ctx, desync) function per_instance_condition(ctx, desync) ``` +- arg: `instances` - how many following instances to execute conditionally. all if not defined. + All following instanced are called only if they have "cond" argument with the "iff" function name and it returns true. The "cond_neg" argument inverts "cond" result. Names are not iff/neg to avoid conflict with other orchestrators. @@ -4402,7 +4406,7 @@ Names are not iff/neg to avoid conflict with other orchestrators. ### stopif ``` -function condition(ctx, desync) +function stopif(ctx, desync) ``` - arg: `iff` - name of the [iff function](#iff-functions) @@ -4462,6 +4466,14 @@ function cond_tcp_ts(desync) Returns `true` if the dissect is tcp and has tcp timestamp option. +#### cond_lua + +``` +function cond_lua(desync) +``` + +Executes a Lua code from the "code" argument. The code returns condition value. Direct addressing of the desync table is possible within the code. + # Auxiliary programs diff --git a/docs/manual.md b/docs/manual.md index 1a026ce..8dbbbcc 100644 --- a/docs/manual.md +++ b/docs/manual.md @@ -223,6 +223,7 @@ - [cond_random](#cond_random) - [cond_payload_str](#cond_payload_str) - [cond_tcp_has_ts](#cond_tcp_has_ts) + - [cond_lua](#cond_lua) - [Вспомогательные программы](#вспомогательные-программы) - [ip2net](#ip2net) - [mdig](#mdig) @@ -3747,10 +3748,10 @@ function plan_instance_pop(desync) ### plan_clear ``` -function plan_clear(desync) +function plan_clear(desync, max) ``` -Очищает [execution plan](#execution_plan) в desync.plan - удаляет все `instance`. +Очищает первые max инстансов, если max задан, либо весь [execution plan](#execution_plan) в desync.plan. ### orchestrate @@ -3764,10 +3765,10 @@ function orchestrate(ctx, desync) ### replay_execution_plan ``` -function replay_execution_plan(desync) +function replay_execution_plan(desync, max) ``` -Выполняет весь [execution plan](#execution_plan) из desync.plan с учетом [instance cutoff](#instance_cutoff) и стандартных фильтров [payload](#внутрипрофильные-фильтры) и [range](#внутрипрофильные-фильтры). +Выполняет max инстансов, если max задан, либо весь [execution plan](#execution_plan) из desync.plan с учетом [instance cutoff](#instance_cutoff) и стандартных фильтров [payload](#внутрипрофильные-фильтры) и [range](#внутрипрофильные-фильтры). # Библиотека программ атаки на DPI zapret-antidpi.lua @@ -4566,6 +4567,7 @@ function condition(ctx, desync) - arg: iff - имя [функции условия](#iff-функции) - arg: neg - инвертировать значение iff. по умолчанию - false +- arg: instances - сколько последующих инстансов выполнять условно. все, если не задано. condition вызывает iff. если iff xor neg = true, выполняются все инстансы plan, иначе план очищается. @@ -4575,13 +4577,15 @@ condition вызывает iff. если iff xor neg = true, выполняют function per_instance_condition(ctx, desync) ``` +- arg: instances - сколько последующих инстансов выполнять условно. все, если не задано. + Все последующие инстансы вызываются только, если у них есть аргумент "cond", содержащий iff функцию, и она возвращает true. Аргумент "cond_neg" инвертирует ее значение. Имена аргументов не iff/neg, чтобы исключить конфликт с другими оркестраторами. ### stopif ``` -function condition(ctx, desync) +function stopif(ctx, desync) ``` - arg: iff - имя [функции условия](#iff-функции) @@ -4641,6 +4645,14 @@ function cond_tcp_ts(desync) Возвращает true, если диссект является tcp и присутствует timestamp tcp option. +#### cond_lua + +``` +function cond_lua(desync) +``` + +Выполняет Lua код из аргумента "code". Код возвращает значение условия через return. Возможна прямая адресация таблицы desync. + # Вспомогательные программы ## ip2net diff --git a/lua/zapret-auto.lua b/lua/zapret-auto.lua index 56b0c08..769567d 100644 --- a/lua/zapret-auto.lua +++ b/lua/zapret-auto.lua @@ -409,6 +409,29 @@ end function cond_tcp_has_ts(desync) return desync.dis.tcp and find_tcp_option(desync.dis.tcp.options, TCP_KIND_TS) end +-- exec lua code in "code" arg and return it's result +function cond_lua(desync) + if not desync.arg.code then + error("cond_lua: no 'code' parameter") + end + local fname = desync.func_instance.."_cond_code" + if not _G[fname] then + local err + _G[fname], err = load(desync.arg.code, fname) + if not _G[fname] then + error(err) + return + end + end + -- allow dynamic code to access desync + _G.desync = desync + local res, v = pcall(_G[fname]) + _G.desync = nil + if not res then + error(v); + end + return v +end -- check iff function available. error if not function require_iff(desync, name) @@ -423,26 +446,33 @@ end -- for example, this can be used by custom protocol detectors -- arg: iff - condition function. takes desync as arg and returns bool. (cant use 'if' because of reserved word) -- arg: neg - invert condition function result +-- arg: instances - how many instances execute conditionally. all if not defined -- test case : --lua-desync=condition:iff=cond_random --lua-desync=argdebug:testarg=1 --lua-desync=argdebug:testarg=2:morearg=xyz function condition(ctx, desync) require_iff(desync, "condition") orchestrate(ctx, desync) if logical_xor(_G[desync.arg.iff](desync), desync.arg.neg) then DLOG("condition: true") - return replay_execution_plan(desync) else DLOG("condition: false") - plan_clear(desync) + plan_clear(desync, tonumber(desync.arg.instances)) + if #desync.plan>0 then + DLOG("condition: executing remaining "..#desync.plan.." instance(s)") + end end + return replay_execution_plan(desync) end -- execute further desync instances. -- each instance may have "cond" and "cond_neg" args. -- "cond" - condition function. "neg" - invert condition function result +-- arg: instances - how many instances execute conditionally. all if not defined function per_instance_condition(ctx, desync) orchestrate(ctx, desync) local verdict = VERDICT_PASS - while true do + local n = 0 + local max = tonumber(desync.arg.instances) + while not max or n0 then + DLOG("per_instance_condition: executing remaining "..#desync.plan.." instance(s) unconditionally") + end + return verdict_aggregate(verdict, replay_execution_plan(desync)) end -- clear execution plan if user provided 'iff' functions returns true diff --git a/lua/zapret-lib.lua b/lua/zapret-lib.lua index 45615d8..5a15b64 100644 --- a/lua/zapret-lib.lua +++ b/lua/zapret-lib.lua @@ -209,8 +209,13 @@ end function plan_instance_pop(desync) return (desync.plan and #desync.plan>0) and table.remove(desync.plan, 1) or nil end -function plan_clear(desync) - while table.remove(desync.plan) do end +function plan_clear(desync, max) + if max then + local n=0 + while n=max then + DLOG("replay_execution_plan: reached max instances limit "..max) end return verdict end