Цель:
Как?
Топология
Формат байткода метода
Заголовки Tiny/Fat
Header
Exception handlers
Tiny Exception handlers sections
Fat Exception handlers sections
Exception handler type
Tokens in IL
Compressed Tokens
Signature scheme
Signature
Constants
Local Signature
Запуск профайлера
Поиск адресов в параметрах
Проверка строковых параметров
Отлов передачи данных
Пример отлова HTTP запроса
На что она обиделась? Том 1.
InvalidProgramException
Проверка логики внедряемого кода
Конфигурирование
Вы всё поняли?
523.32K

CLR Profiling injection

1. Цель:

•Контроль за передачей данных
между системами
•Отслеживание количества запросов
•Мониторинг задержки, количества
запросов в очереди
•Определение иерархии вызовов
•Построение топологии

2. Как?

• CLR Profiling injection во время Just-in-Time
компиляции.
• Встраивание в методы, отвечающие за
передачу данных(Http, Ftp, FileStream) в
System.dll Например, WebClient.
• Поиск строковых параметров, подходящих
под формат адреса.

3. Топология

Сервер
Процесс
Сервер
Процесс
Процесс
Процесс
Сервер
Процесс
Процесс
Процесс
Процесс

4. Формат байткода метода

• Header(Tiny/Fat)
• IL instructions
• Extra sections(Exception handlers)

5. Заголовки Tiny/Fat

When you get the physical starting address of a method (after calculating it from
the RVA), you should begin with checking the first byte. The two least significant
bits tell the type of the method header. If the value is 2 then it's a tiny header, if 3
then it's a fat header.
There are some conditions that must be met for tiny header to be used. These are
the following:
• No local variables are allowed
• No exceptions
• No extra data sections
• The operand stack shall be no bigger than 8 entries
If any of these requirements not met, a fat header will be used.
The tiny header is very simple as it's only 1 byte. The two least significant bits have
already been used to tell the format of the header thus the remaining 6 bits tell
the length (in bytes) of the method.

6. Header

Offset
Size
0 12 (bits)
Field
Flags
Description
Flags (CorILMethod_FatFormat shall be set in bits 0:1).
4 (bits)
Size
Size of this header expressed as the count of 4-byte integers occupied (currently 3).
12 (bits)
2
2 MaxStack
Maximum number of items on the operand stack.
4
4 CodeSize
Size in bytes of the actual method body
8
4 LocalVarSigTok
Meta Data token for a signature describing the layout of the local variables for the method. 0
means there are no local variables present. This field references a stand-alone signature in the
MetaData tables, which references an entry in the #Blob stream.
Flag
CorILMethod_FatFormat
CorILMethod_TinyFormat
CorILMethod_MoreSects
Value
0x3
0x2
0x8
Description
Method header is fat.
Method header is tiny.
More sections follow after this header.
CorILMethod_InitLocals
0x10
Call default constructor on all local variables.

7. Exception handlers

Extra sections can have a Fat (1 byte flags, 3 bytes size) or a Small header (1 byte flags, 1 byte
size); the size includes the header size. The type of the header and the type of the section is
specified in the first byte, of course:
Flag
CorILMethod_Sect_EHTable
Value
0x1
Description
Exception handling data.
CorILMethod_Sect_OptILTable
0x2
Reserved, shall be 0.
CorILMethod_Sect_FatFormat
0x40
CorILMethod_Sect_MoreSects
0x80
Data format is of the Fat variety, meaning there is a 3-byte length. If not
set, the header is Small with a 1-byte length.
Another data section occurs after this current section.

8. Tiny Exception handlers sections

Offset
0
Size
1
Field
Kind
Description
Flags as described above.
1
2
4
1
2
n
DataSize
Reserved
Clauses
Size of the data for the block, including the header, say n*12+4.
Padding, always 0.
nsmall exception clauses.
Offset
0
2
Size
2
2
Field
Flags
TryOffset
Description
Flags, see below.
Offset in bytes of try block from the start of the header.
4
5
1
2
TryLength
HandlerOffset
Length in bytes of the try block
Location of the handler for this try block
7
1
HandlerLength
Size of the handler code in bytes
8
4
ClassToken
Meta data token for a type-based exception handler
8
4
FilterOffset
Offset in method body for filter-based exception handler

9. Fat Exception handlers sections

Offset
Size
Field
Description
0
1
Kind
Which type of exception block is being used
1
3
DataSize
Size of the data for the block, including the header, say n*24+4.
4
n
Clauses
nfat exception clauses.
Offset
Size
Field
Description
0
4
Flags
Flags, see below.
4
4
TryOffset
Offset in bytes of try block from the start of the header.
8
4
TryLength
Length in bytes of the try block
12
4
HandlerOffset
Location of the handler for this try block
16
4
HandlerLength
Size of the handler code in bytes
20
4
ClassToken
Meta data token for a type-based exception handler
20
4
FilterOffset
Offset in method body for filter-based exception handler

10. Exception handler type

Flag
COR_ILEXCEPTION_CLAUSE_EXCEPTION
Value
0x0000
Description
A typed exception clause
COR_ILEXCEPTION_CLAUSE_FILTER
0x0001
An exception filter and handler clause
COR_ILEXCEPTION_CLAUSE_FINALLY
0x0002
A finally clause
COR_ILEXCEPTION_CLAUSE_FAULT
0x0004
Fault clause (finally that is called on the
exception only)
• catch - I need to do something with the exception object when an
exception occurs.
• fault - I don't need the exception object, but I need to do something when
an exception occurs. (Currently, no languages provide support for fault.)
• finally - I don't need the exception object, but I need to do something
before the end of the function.
• filter - similar to a catch block but can run arbitrary code to determine
whether it wants to handle the error, rather than just matching on type.
This block has access to the exception object, and has the same effect on
the exception stack trace as a catch block.

11. Tokens in IL

Table ID
Table Type
0x1
TypeRef - Found when casting or checking
0x2
TypeDef - Found when casting or checking
0x6
Method - Found when calling
0xa
MemberRef - Found when calling or loading (field instance)
0x11
StandAloneSig - Found when calling
0x1b
TypeSpec - Found when casting or checking
0x2b
MethodSpec - Found when calling

12. Compressed Tokens


Signatures are compressed before being stored into the #Blob heap by compressing the integers embedded in the signature.
In contrast to normal integers that have fixed size, compressed integers use only as much space as needed, almost all
signatures use integer compression instead of normal, fixed size integers. Because vast majority numbers in signatures lies
below 128, space saving is significant. Below you can see encoding alghoritm copied from specification:
If the value lies between 0 (0x00) and 127 (0x7F), inclusive, encode as a one-byte integer (bit 7 is clear, value held in bits 6
through 0)
If the value lies between 2<sup>8</sup> (0x80) and 2<sup>14</sup> - 1 (0x3FFF), inclusive, encode as a 2-byte integer with
bit 15 set, bit 14 clear (value held in bits 13 through 0)
Otherwise, encode as a 4-byte integer, with bit 31 set, bit 30 set, bit 29 clear (value held in bits 28 through 0)
A null string should be represented with the reserved single byte 0xFF, and no following data
Orginal value (32-bit)
Compressed value
Saved bytes
Hex
00 00 00 7F
7F
3
Binary
00000000 0000000 00000000 01111111
01111111
-
Orginal value (32-bit)
Compressed value
Saved bytes
Hex
00 00 00 80
80 80
2
Binary
00000000 0000000 00000000 10000000
10000000 10000000
-
Orginal value (32-bit)
Compressed value
Saved bytes
Hex
00 00 2E 57
AE 57
2
Binary
00000000 0000000 00101110 01010111
10101110 01010111
-

13. Signature scheme

14. Signature

"

15. Constants

Name
Value
Remarks
Name
Value
Remarks
ELEMENT_TYPE_END
0x00
Marks end of a list
ELEMENT_TYPE_VALUETYPE
0x11
A value type modifier, followed by TypeDef or TypeRef token
ELEMENT_TYPE_VOID
0x01
System.Void
ELEMENT_TYPE_CLASS
0x12
A class type modifier, followed by TypeDef or TypeRef token
ELEMENT_TYPE_BOOL
EAN
0x02
System.Boolean
ELEMENT_TYPE_VAR
0x13
Generic parameter in a generic type definition, represented as number
ELEMENT_TYPE_CHAR
0x03
System.Char
ELEMENT_TYPE_ARRAY
0x14
A multi-dimensional array type modifier.
ELEMENT_TYPE_I1
0x04
System.SByte
ELEMENT_TYPE_GENERICINST
0x15
Generic type instantiation. Followed by type type-arg-count type-1 ... type-n
ELEMENT_TYPE_U1
0x05
System.Byte
ELEMENT_TYPE_TYPEDBYREF
0x16
A typed reference.
ELEMENT_TYPE_I2
0x06
System.Int16
ELEMENT_TYPE_I
0x18
System.IntPtr
ELEMENT_TYPE_U2
0x07
System.UInt16
ELEMENT_TYPE_U
0x19
System.UIntPtr
ELEMENT_TYPE_I4
0x08
System.Int32
ELEMENT_TYPE_FNPTR
0x1B
A pointer to a function, followed by full method signature
ELEMENT_TYPE_U4
0x09
System.UInt32
ELEMENT_TYPE_OBJECT
0x1C
System.Object
ELEMENT_TYPE_I8
0x0A
System.Int64
ELEMENT_TYPE_SZARRAY
0x1D
A single-dimensional, zero lower-bound array type modifier.
ELEMENT_TYPE_U8
0x0B
System.UInt64
ELEMENT_TYPE_MVAR
0x1E
Generic parameter in a generic method definition, represented as number
ELEMENT_TYPE_R4
0x0C
System.Single
ELEMENT_TYPE_CMOD_REQD
0x1F
Required modifier, followed by a TypeDef or TypeRef token
ELEMENT_TYPE_R8
0x0D
System.Double
ELEMENT_TYPE_CMOD_OPT
0x20
Optional modifier, followed by a TypeDef or TypeRef token
ELEMENT_TYPE_STRIN
0x0E
G
ELEMENT_TYPE_INTERNAL
0x21
Implemented within the CLI
System.String
ELEMENT_TYPE_MODIFIER
0x40
ORed with following element types
ELEMENT_TYPE_SENTINEL
0x41
Sentinel for vararg method signature
ELEMENT_TYPE_PTR
0x0F
Unmanaged
pointer, followed
by
the Type element.
ELEMENT_TYPE_PINNED
0x45
Denotes a local variable that points at a pinned object
0x50
Indicates an argument of type System.Type.
ELEMENT_TYPE_BYREF 0x10
Managed pointer,
followed by
the Type element.
0x51
Used in custom attributes to specify a boxed object (§23.3 in the ECMA-355 specification).
0x52
Reserved
0x53
Used in custom attributes to indicate a FIELD (§22.10, §23.3 in the ECMA-355
specification).
0x54
Used in custom attributes to indicate a PROPERTY (§22.10, §23.3 in the ECMA-355
specification).
0x55
Used in custom attributes to specify an enum (§23.3 in the ECMA-355 specification).

16. Local Signature

public int [] ReturnTheNubmers (string [] [] number)
{
int [] twenty = new int [20];
int [,] twenty2 = new int [20, 20];
return twenty;
}
07 03 1d 08 14 08 02 00 02 00 00 1d 08
Calling
Convention
Local Count
Parameter 1 Parameter 2
0x07
0x03
0x1d 0x08
0x14 0x08 0x02 0x00 0x02
0x00 0x00
Parameter 3
0x1d 0x08

17.

18. Запуск профайлера

• В переменных окружения добавить параметры
профайлера(включение и адрес dll профайлера на
C++).

19. Поиск адресов в параметрах

• Создать dll на C# с методами, принимающими URI и string.
• Зарегистрировать в GAC.
• Отловить методы исполняемой программы(клиента). Анализируя
сигнатуру методы принять решение об inject’е.
• Добавить строку(имя метода) в таблицу строк и использовать токен.
• Внедрить байткод после header’а.
• Скорректировать SEH, если есть.

20. Проверка строковых параметров


static Regex regex1;
static Regex regex2;
public static void CheckString(string argument, string methodName, string assemblyName)
{
if (argument == null)
{
Console.WriteLine("check null from the method '" + methodName + "'");
return;
}
if (regex1 == null)
{
string pattern1 = @"^\\{2}[\w-]+(\\{1}(([\w-][\w-\s]*[\w-]+[$$]?)|([\w-][$$]?$)))+";
string pattern2 = @"^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$";
regex1 = new Regex(pattern1, RegexOptions.Compiled);
regex2 = new Regex(pattern2, RegexOptions.Compiled);
}
try
{
Console.WriteLine("check " + argument.ToString() + " from the method '" + methodName + "'");
if (regex1.IsMatch(argument) || regex2.IsMatch(argument))
{
System.IO.File.WriteAllText(@"C:\temp\log\" + Guid.NewGuid().ToString() + ".txt", "check \"" + argument.ToString() + "\" from the method '" + methodName + "'");
Console.WriteLine("Network path(possible network request) found \"" + argument + "\"");
}
else
System.IO.File.WriteAllText(@"C:\temp\log\all\" + Guid.NewGuid().ToString() + ".txt", "check \"" + argument.ToString() + "\" from the method '" + methodName + "'");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
}

21. Отлов передачи данных


Создать dll на C# с методами по два(начало и окончание) для каждого метода System.dll.
Зарегистрировать в GAC.
Установить флаг наличия SEH.
Добавить локальную переменную того же типа, что и возвращаемое значение(если не
void). Тип возвращаемого значения в сигнатуре метода.
Внедрить байткод после header’а, вызывающий метод старта.
Заменить все ret(return) на leave.s и задать offset на конец байткода метода.
Добавить загрузку значения из стека в локальную переменную.
Добавить leave.s
Добавить вызов метода финиша(Он попадёт в finally block).
Добавить SEH.
Скорректировать SEH, если есть.

22. Пример отлова HTTP запроса


static Dictionary<object, DateTime> Downloads = new Dictionary<object, DateTime>();
public static void StartDownloadBits(object webRequest)
{
Console.WriteLine("Started at " + DateTime.Now.ToString("hh\\:mm\\:ss\\.fff"));
Downloads.Add(webRequest, DateTime.Now);
}
public static void FinishDownloadBits(object webRequest)
{
try
{
Console.Write("Finished at " + DateTime.Now.ToString("hh\\:mm\\:ss\\.fff") + ".");
Console.Write("Latency is " + (DateTime.Now - Downloads[webRequest]).ToString("hh\\:mm\\:ss\\.fff") + ".");
Console.Write("Items in queue: " + (Downloads.Count - 1).ToString());
Console.WriteLine();
if (Downloads.ContainsKey(webRequest))
{
Downloads.Remove(webRequest);
}
else
{
Console.WriteLine("NotFound!!!!!!!!!!!!!!!");
}
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
}

23. На что она обиделась? Том 1.

24. InvalidProgramException


Unknown calling convention.
Unknown ELEMENT_TYPE.
Stack is too large.
fall thru end of the method.
try start >= try end.
try end > code size.
handler >= handler end.
handler end > code size.
filter >= code size.
Try starts in the middle of an instruction.
Handler starts in the middle of an instruction.
Filter starts in the middle of an instruction.
Try block overlap with another block.
Try and filter/handler blocks are equivalent.
Try shared between finally and fault.
Handler block overlaps with another block.
Handler block is the same as another block.
Filter block overlaps with another block.
Filter block is the same as another block.
Filter contains try.
Filter contains handler.
Nested filters.
filter >= code size.
Filter starts in the middle of an
instruction.
jmp / exception into the middle of an
instruction.
Unrecognized local variable number.
Unrecognized argument number.
Code size is zero.
Method ends in the middle of an
instruction.
Branch out of the method.
Finally handler blocks overlap.
Lexical nesting.
Innermost exception blocks should be
declared first.
filter block should immediately precede
handler block.

25. Проверка логики внедряемого кода

• Используя библиотеку Monoceciler
внедрить код и сохранить полученную
сборку. Либо повторить предполагаемый
код и скомпилировать самостоятельно.
• Проверить полученные сборки с помощью
PEVerify.

26. Конфигурирование

• Отлов передачи данных
• Анализ методов, в которых используются
адреса
• ???

27. Вы всё поняли?

English     Русский Правила