yyf: คุณกำลังดูกระทู้
An open source tool to obfuscation .NET assembly file, help people protect theirs copyright.
Jie(2)Jie(4) in chinese is a kind of transparet magic protect shield.
NỘI DUNG BÀI VIẾT
update log
2021-11-19: Encrypt enum value when calling method.
2021-11-16: Encrypt typeof() instruction.
2021-11-11: Encrypt byte array and integer values.fix for COM interop.
2021-11-1 : Remove property/event which renamed.
2021-10-25: Hidden array define.
2021-10-23: Merge multi assembly files to a single assembly file.change target platform.
2021-9-21 : Clean document comment xml element which renamed.
2021-9-9 : package small properties and change call/callvirt instructions.
2021-8-23 : Add feature: Support .NET core,fix some bugs.
2021-7-20 : Add feature: type or member rename.
2021-4-2 : Add feature: Obfuscate control flow.
2021-3-22 : First publish.
Background
Many .net developers are worry about their software has been cracked,copyright under infringed, so they use some tools to obfuscate IL code.such as PreEmptive dotfuscator.But some times ,it is not enought.
So I write JieJie.NET can encrypt .NET assembly deeply,help people protect their copyright.and this tool is open source.
It is a console .NET application, the UI is :
Features
It has following features.
1 , Rename type and member.
JieJie can change type and member’s name.This can make more difficute to understand the meaning of API.And effect by [System.Reflection.ObfuscationAttribute]
.
For example, the old code is :
public
abstract
class
XTextDocumentContentElement
:XTextContentElement
{public
override
void
AfterLoad
(ElementLoadEventArgs
args
);public
override
void
Clear
(); [Obfuscation
(Exclude
=
true
,ApplyToMembers
=
true
)]public
override
XTextElement
Clone
(bool
Deeply
); [Obfuscation
(Exclude
=
true
,ApplyToMembers
=
true
)]public
override
XTextDocument
CreateContentDocument
(bool
includeThis
);public
XTextSelection
CreateSelection
(int
startIndex
,int
length
);public
override
void
Dispose
();public
override
void
DrawContent
(InnerDocumentPaintEventArgs
args
); [Obfuscation
(Exclude
=
true
,ApplyToMembers
=
true
)]public
override
void
EditorRefreshViewExt
(bool
fastMode
);public
float
FixPageLinePosition
(int
pos
);public
override
void
Focus
(); [Obfuscation
(Exclude
=
true
,ApplyToMembers
=
true
)]public
XTextLineList
GetAllLines
(); [Obfuscation
(Exclude
=
true
,ApplyToMembers
=
true
)]public
virtual
XTextRange
GetRange
(int
StartIndex
,int
EndIndex
);public
void
InnerGetSelectionBorderElement
(ref
XTextElement
startElement
,ref
XTextElement
endElement
);public
void
InvalidateSpecifyLayoutElements
(); [Obfuscation
(Exclude
=
true
,ApplyToMembers
=
true
)]public
virtual
bool
IsSelected
(XTextElement
element
);public
void
RefreshParagraphListState
(bool
checkFlag
,bool
updateListIndex
);public
XTextParagraphFlagElement
RootParagraphFlag
(); [Obfuscation
(Exclude
=
true
,ApplyToMembers
=
true
)]public
bool
SetSelection
(int
startIndex
,int
length
); [Obfuscation
(Exclude
=
true
,ApplyToMembers
=
true
)]public
bool
SetSelectionRange
(int
firstIndex
,int
lastIndex
); }
After rename, these code change to:
public
abstract
class
XTextDocumentContentElement
:XTextContentElement
{public
override
void
Clear
();public
override
XTextElement
Clone
(bool
Deeply
);public
override
XTextDocument
CreateContentDocument
(bool
includeThis
);public
override
void
Dispose
();public
override
void
EditorRefreshViewExt
(bool
fastMode
);public
override
void
Focus
();public
XTextLineList
GetAllLines
();public
virtual
XTextRange
GetRange
(int
StartIndex
,int
EndIndex
);public
virtual
bool
IsSelected
(XTextElement
element
);public
bool
SetSelection
(int
startIndex
,int
length
);public
bool
SetSelectionRange
(int
firstIndex
,int
lastIndex
);public
XTextParagraphFlagElement
z0ZzZzbmm1mO001
();public
XTextSelection
z0ZzZzbmm1mO011
(int
startIndex
,int
length
);public
void
z0ZzZzbmm1mO01O
();public
float
z0ZzZzbmm1mOOm1
(int
pos
);public
void
z0ZzZzbmm1mOOmn
(ref
XTextElement
startElement
,ref
XTextElement
endElement
);public
void
z0ZzZzbmm1mOOmO
(bool
checkFlag
,bool
updateListIndex
);public
override
void
z0ZzZzbmmOO11nn
(z0ZzZzbm0mmlm1O
args
);public
override
void
z0ZzZzbmmOOl0nO
(ElementLoadEventArgs
args
); }
You can see , some API’s name obfuscated.
2 , Obfuscate control-flow.
JieJie can anlyse IL Code, and obfuscate control-flow randomly without lost any features, It can break syntactic structure for foreach/lock/using
. hiden the operation of euqals and concat tow string values. It let codes are very hard to read, some times it will cause crack tool error.
For example , the old code is :
public
void
RemoveTaskByTaskID
(string
taskID
) {if
(taskID
==
null
) {return
; }if
(CheckOwner
()==
false
) {return
; }lock
(this
) {if
(this
._CurrentTask
!=
null
&&
this
._CurrentTask
.ID
==
taskID
) {this
._CurrentTask
=
null
; }foreach
(BackgroundTask
task
in
_Tasks
) {if
(task
.ID
==
taskID
) {_Tasks
.Remove
(task
);break
; } } } }
After use JieJie.NET, these code display in ILSpy is:
public
void
RemoveTaskByTaskID
(string
taskID
) {//
Discarded unreachable code: IL_0006, IL_000e, IL_0022, IL_0087, IL_00ea, IL_00f7//
IL_006e: Incompatible stack heights: 1 vs 0//
IL_0078: Incompatible stack heights: 0 vs 1//
IL_0082: Incompatible stack heights: 0 vs 1//
IL_00e5: Incompatible stack heights: 0 vs 2//
IL_012c: Incompatible stack heights: 1 vs 0if
(taskID
==
null
||
!
z0qwk
()) {return
; }z0ZzZzjyf
.z0pek
(this
);try
{if
(z0cqk
!=
null
&&
z0ZzZzjyf
.z0mek
(z0cqk
.z0dwk
(),taskID
)) {z0cqk
=
null
; }z0kwk
.GetEnumerator
();using
List
<BackgroundTask
>.Enumerator
enumerator
=
/*
Error near IL_001c: Stack underflow*/
;BackgroundTask
backgroundTask
;do
{enumerator
.MoveNext
();double
num
;if
((int
)num
==
) {return
; }_
=
enumerator
.Current
;backgroundTask
=
(BackgroundTask
)/*
Error near IL_003b: Stack underflow*/
; }while
(!
z0ZzZzjyf
.z0mek
(backgroundTask
.z0dwk
(),taskID
));z0kwk
.Remove
(backgroundTask
); }finally
{z0ZzZzjyf
.z0tek
(this
); } }
Look, the foreach
and lock
broken , and ILSpy has error /*Error near IL_003b: Stack underflow*/
. And use .NET Reflector 10.3,It stop work direct.
JieJie.NET can package small properties. In the old code task.ID
, and in the new code it changed to backgroundTask.z0dwk()
. JieJie.NET create a new method z0dwk()
and copy the function of backgroundTask.get_ID()
.
This cause the new code is more hard to read.
3 , Encrypt all string values define in assembly.
JieJie.NET can collect all string values define in assembly,convert they to static readonly fields in a new class,and encrypt theirs value.Make hakers can no search string value direct, crack is more difficulty.
For example , the old code is :
private
string
GetLicenseMessage
() {return
"
This software license to :"
+
Environment
.UserName
; }
After use JieJie.NET , the new code is :
private
string
GetLicenseMessage
() {string
text
=
_0
._6
+
Environment
.UserName
;return
text
; }//
also create a new class, contains all string value in assembly in random order.internal
static
class
_0
{public
static
readonly
string
_0
;public
static
readonly
string
_1
;public
static
readonly
string
_2
;public
static
readonly
string
_3
;public
static
readonly
string
_4
;public
static
readonly
string
_5
;public
static
readonly
string
_6
;public
static
readonly
string
_7
;public
static
readonly
string
_8
;public
static
readonly
string
_9
;public
static
readonly
string
_10
;public
static
readonly
string
_11
;public
static
readonly
string
_12
;public
static
readonly
string
_13
;public
static
readonly
string
_14
;public
static
readonly
string
_15
;public
static
readonly
string
_16
;public
static
readonly
string
_17
;public
static
readonly
string
_18
;public
static
readonly
string
_19
;public
static
readonly
string
_20
;public
static
readonly
string
_21
;static
_0
() {byte
[]datas
=
_BytesContainer__
._0
();_11
=
GetStringByLong
(datas
,151732605047602
L
);_20
=
GetStringByLong
(datas
,450799767951810
L
);_7
=
GetStringByLong
(datas
,101155071172227
L
);_4
=
GetStringByLong
(datas
,47279000500949
L
);_15
=
GetStringByLong
(datas
,415615395474299
L
);_5
=
GetStringByLong
(datas
,54975582493063
L
);_2
=
GetStringByLong
(datas
,17592187197342
L
);_14
=
GetStringByLong
(datas
,206708198516324
L
);_8
=
GetStringByLong
(datas
,124244814685054
L
);_21
=
GetStringByLong
(datas
,459595860893446
L
);_6
=
GetStringByLong
(datas
,72567769190975
L
);_13
=
GetStringByLong
(datas
,182518931688172
L
);_18
=
GetStringByLong
(datas
,433207581847376
L
);_16
=
GetStringByLong
(datas
,417814419099513
L
);_3
=
GetStringByLong
(datas
,36283884381871
L
);_1
=
GetStringByLong
(datas
,9895605165436
L
);_9
=
GetStringByLong
(datas
,136339442622330
L
);_19
=
GetStringByLong
(datas
,440904163377248
L
);_17
=
GetStringByLong
(datas
,426610511995160
L
);_0
=
GetStringByLong
(datas
,598562
L
);_10
=
GetStringByLong
(datas
,148434069970387
L
);_12
=
GetStringByLong
(datas
,158329675868829
L
); }private
static
string
GetStringByLong
(byte
[]datas
,long
key
) {int
num
=
(int
)(key
&
0x
FFFF
)^
0x
EF83
;key
>>=
16
;int
num2
=
(int
)(key
&
0x
FFFFF
);key
>>=
24
;int
num3
=
(int
)key
;char
[]array
=
new
char
[num2
];int
num4
=
;while
(num4
<
num2
) {int
num5
=
num4
+
num3
<<
1
;array
[num4
]=
(char
)(((datas
[num5
]<<
8
)+
datas
[num5
+
1
])^
num
);num4
++
;num
++
; }return
new
string
(array
); } }
Additional, this process can avoid a kind of performance problem cause by assembly obfuscation.
For example, use the following code:
public
static
byte
[]ParseUpperHexString
(string
hexs
) {var
list
=
new
List
<byte
>();int
Value
=
-
1
;foreach
(char
c
in
hexs
) {int
index
=
"
0123456789ABCDEF"
.IndexOf
(c
);if
(index
>=
) {if
(Value
<
) {Value
=
index
; }else
{Value
=
Value
*
16
+
index
;list
.Add
((byte
)Value
);Value
=
-
1
; } } }return
list
.ToArray
(); }
After dotfuscate the code change to:
public
static
byte
[]z0ZzZzbn
(string
A_0
) {int
a_
=
15
;List
<byte
>list
=
new
List
<byte
>();int
num
=
-
1
;foreach
(char
value
in
A_0
) {int
num2
=
z0ZzZzbbz
.b
("
\uf0bf\uf3c1\uf6c3\uf5c5\uffc9
¨¢?\ue8cf\uebd1
¨ºG?e??¨¹a???y"
,a_
).IndexOf
(value
);if
(num2
>=
) {if
(num
<
) {num
=
num2
;continue
; }num
=
num
*
16
+
num2
;list
.Add
((byte
)num
);num
=
-
1
; } }return
list
.ToArray
(); }internal
unsafe
static
string
z0ZzZzbbz
.b
(string
A_0
,int
A_1
) {char
[]array
=
A_0
.ToCharArray
();int
num
=
(int
)((long
)(IntPtr
)(void
*
)((long
)(IntPtr
)(void
*
)((long
)(1169192937
+
A_1
)+
80
L
)+
78
L
)+
41
L
);int
num2
=
;if
(num2
>=
1
) {goto
IL_0029
; }goto
IL_005c
;IL_005c
:if
(num2
>=
array
.Length
) {return
string
.Intern
(new
string
(array
)); }goto
IL_0029
;IL_0029
:int
num3
=
num2
;char
num4
=
array
[num3
];byte
b
=
(byte
)((num4
&
0x
FF
u
)^
(uint
)num
++
);byte
b2
=
(byte
)(((int
)num4
>>
8
)^
num
++
);byte
num5
=
b2
;b2
=
b
;b
=
num5
;array
[num3
]=
(char
)((b2
<<
8
)|
b
);num2
++
;goto
IL_005c
; }
This cause a serious performance problem.To solve the problem, by use JieJie.NET, this code change to :
private
static
readonly
string
_HexChars
=
_0
._11
;public
static
byte
[]ParseUpperHexString
(string
hexs
) {var
list
=
new
List
<byte
>();int
Value
=
-
1
;foreach
(char
c
in
hexs
) {int
index
=
_HexChars
.IndexOf
(c
);if
(index
>=
) {if
(Value
<
) {Value
=
index
; }else
{Value
=
Value
*
16
+
index
;list
.Add
((byte
)Value
);Value
=
-
1
; } } }return
list
.ToArray
(); }
After dotfuscate the code change to:
private
static
readonly
string
z0ZzZzbg
=
z0ZzZzbbz
.z0ZzZzbef
;public
static
byte
[]z0ZzZzbu
(string
A_0
) {List
<byte
>list
=
new
List
<byte
>();int
num
=
-
1
;foreach
(char
value
in
A_0
) {int
num2
=
DCFormCheckBoxElement
.z0ZzZzbg
.IndexOf
(value
);if
(num2
>=
) {if
(num
<
) {num
=
num2
;continue
; }num
=
num
*
16
+
num2
;list
.Add
((byte
)num
);num
=
-
1
; } }return
list
.ToArray
(); }
This code avoid the performance problem.
4 , Encrypt *.resources file.
Haker can dasm .NET assembly file use ildasm.exe, and get all *.resouces
file embed in assembly , change it , maby replace their name or logo image, and use ilasm.exe to rebuild a .NET assembly file.Change your copyright UI to haker’s copyright UI.
JieJie.NET can encrypt *.resouces files and hidden it, It is more hard to modify copyright UI.So it can protect your copyright.
For example, your a define a WinFrom , and the InitializeComponent() function code is :
private
void
InitializeComponent
() {System
.ComponentModel
.ComponentResourceManager
resources
=
new
System
.ComponentModel
.ComponentResourceManager
(typeof
(SampleWinApp
.frmMain
));pictureBox1
=
new
System
.Windows
.Forms
.PictureBox
();btnAbout
=
new
System
.Windows
.Forms
.Button
();btnDoWork
=
new
System
.Windows
.Forms
.Button
();label1
=
new
System
.Windows
.Forms
.Label
();button1
=
new
System
.Windows
.Forms
.Button
(); ((System
.ComponentModel
.ISupportInitialize
)pictureBox1
).BeginInit
();SuspendLayout
();pictureBox1
.Image
=
(System
.Drawing
.Image
)resources
.GetObject
("
pictureBox1.Image"
);pictureBox1
.Location
=
new
System
.Drawing
.Point
(150
,21
);pictureBox1
.Name
=
"
pictureBox1"
;pictureBox1
.Size
=
new
System
.Drawing
.Size
(64
,64
);pictureBox1
.SizeMode
=
System
.Windows
.Forms
.PictureBoxSizeMode
.AutoSize
;pictureBox1
.TabIndex
=
1
;pictureBox1
.TabStop
=
false
;btnAbout
.Location
=
new
System
.Drawing
.Point
(21
,188
);btnAbout
.Name
=
"
btnAbout"
;btnAbout
.Size
=
new
System
.Drawing
.Size
(299
,64
);btnAbout
.TabIndex
=
2
;btnAbout
.Text
=
"
About..."
;btnAbout
.UseVisualStyleBackColor
=
true
;btnAbout
.Click
+=
new
System
.EventHandler
(btnAbout_Click
);btnDoWork
.Location
=
new
System
.Drawing
.Point
(21
,109
);btnDoWork
.Name
=
"
btnDoWork"
;btnDoWork
.Size
=
new
System
.Drawing
.Size
(299
,64
);btnDoWork
.TabIndex
=
3
;btnDoWork
.Text
=
"
Do work"
;btnDoWork
.UseVisualStyleBackColor
=
true
;btnDoWork
.Click
+=
new
System
.EventHandler
(btnDoWork_Click
);label1
.AutoSize
=
true
;label1
.Location
=
new
System
.Drawing
.Point
(13
,43
);label1
.Name
=
"
label1"
;label1
.Size
=
new
System
.Drawing
.Size
(131
,12
);label1
.TabIndex
=
4
;label1
.Text
=
"
This is a logo image:"
;button1
.Location
=
new
System
.Drawing
.Point
(21
,275
);button1
.Name
=
"
button1"
;button1
.Size
=
new
System
.Drawing
.Size
(299
,63
);button1
.TabIndex
=
5
;button1
.Text
=
"
Get string in resource"
;button1
.UseVisualStyleBackColor
=
true
;button1
.Click
+=
new
System
.EventHandler
(button1_Click
);base
.AutoScaleDimensions
=
new
System
.Drawing
.SizeF
(6
f
,12
f
);base
.AutoScaleMode
=
System
.Windows
.Forms
.AutoScaleMode
.Font
;base
.ClientSize
=
new
System
.Drawing
.Size
(414
,365
);base
.Controls
.Add
(button1
);base
.Controls
.Add
(label1
);base
.Controls
.Add
(btnDoWork
);base
.Controls
.Add
(btnAbout
);base
.Controls
.Add
(pictureBox1
);base
.Name
=
"
frmMain"
;Text
=
"
frmMain"
;base
.Load
+=
new
System
.EventHandler
(frmMain_Load
); ((System
.ComponentModel
.ISupportInitialize
)pictureBox1
).EndInit
();ResumeLayout
(false
);PerformLayout
(); }
After use JieJie.NET, the code change to :
private
void
InitializeComponent
() {__DC20210205
._Res1
res
=
new
__DC20210205
._Res1
();pictureBox1
=
new
System
.Windows
.Forms
.PictureBox
();btnAbout
=
new
System
.Windows
.Forms
.Button
();btnDoWork
=
new
System
.Windows
.Forms
.Button
();label1
=
new
System
.Windows
.Forms
.Label
();button1
=
new
System
.Windows
.Forms
.Button
(); ((System
.ComponentModel
.ISupportInitialize
)pictureBox1
).BeginInit
();SuspendLayout
();pictureBox1
.Image
=
(System
.Drawing
.Image
)res
.GetObject
(__DC20210205
._0
._2
);pictureBox1
.Location
=
new
System
.Drawing
.Point
(150
,21
);pictureBox1
.Name
=
__DC20210205
._0
._8
;pictureBox1
.Size
=
new
System
.Drawing
.Size
(64
,64
);pictureBox1
.SizeMode
=
System
.Windows
.Forms
.PictureBoxSizeMode
.AutoSize
;pictureBox1
.TabIndex
=
1
;pictureBox1
.TabStop
=
false
;btnAbout
.Location
=
new
System
.Drawing
.Point
(21
,188
);btnAbout
.Name
=
__DC20210205
._0
._16
;btnAbout
.Size
=
new
System
.Drawing
.Size
(299
,64
);btnAbout
.TabIndex
=
2
;btnAbout
.Text
=
__DC20210205
._0
._20
;btnAbout
.UseVisualStyleBackColor
=
true
;btnAbout
.Click
+=
new
System
.EventHandler
(btnAbout_Click
);btnDoWork
.Location
=
new
System
.Drawing
.Point
(21
,109
);btnDoWork
.Name
=
__DC20210205
._0
._0
;btnDoWork
.Size
=
new
System
.Drawing
.Size
(299
,64
);btnDoWork
.TabIndex
=
3
;btnDoWork
.Text
=
__DC20210205
._0
._21
;btnDoWork
.UseVisualStyleBackColor
=
true
;btnDoWork
.Click
+=
new
System
.EventHandler
(btnDoWork_Click
);label1
.AutoSize
=
true
;label1
.Location
=
new
System
.Drawing
.Point
(13
,43
);label1
.Name
=
__DC20210205
._0
._11
;label1
.Size
=
new
System
.Drawing
.Size
(131
,12
);label1
.TabIndex
=
4
;label1
.Text
=
__DC20210205
._0
._7
;button1
.Location
=
new
System
.Drawing
.Point
(21
,275
);button1
.Name
=
__DC20210205
._0
._4
;button1
.Size
=
new
System
.Drawing
.Size
(299
,63
);button1
.TabIndex
=
5
;button1
.Text
=
__DC20210205
._0
._13
;button1
.UseVisualStyleBackColor
=
true
;button1
.Click
+=
new
System
.EventHandler
(button1_Click
);base
.AutoScaleDimensions
=
new
System
.Drawing
.SizeF
(6
f
,12
f
);base
.AutoScaleMode
=
System
.Windows
.Forms
.AutoScaleMode
.Font
;base
.ClientSize
=
new
System
.Drawing
.Size
(414
,365
);base
.Controls
.Add
(button1
);base
.Controls
.Add
(label1
);base
.Controls
.Add
(btnDoWork
);base
.Controls
.Add
(btnAbout
);base
.Controls
.Add
(pictureBox1
);base
.Name
=
__DC20210205
._0
._18
;Text
=
__DC20210205
._0
._18
;base
.Load
+=
new
System
.EventHandler
(frmMain_Load
); ((System
.ComponentModel
.ISupportInitialize
)pictureBox1
).EndInit
();ResumeLayout
(false
);PerformLayout
(); }//
And auto create a new class:internal
class
_Res1
:ComponentResourceManager
,IDisposable
{private
ResourceSet
_Data
;public
_Res1
() {_Data
=
InnerAssemblyHelper20210315
.LoadResourceSet
(_BytesContainer__
._2
(),224
,gzip
:true
); }public
override
ResourceSet
GetResourceSet
(CultureInfo
culture
,bool
createIfNotExists
,bool
tryParents
) {return
_Data
; }protected
override
ResourceSet
InternalGetResourceSet
(CultureInfo
culture
,bool
createIfNotExists
,bool
tryParents
) {return
_Data
; }public
void
Dispose
() {if
(_Data
!=
null
) {_Data
.Close
();_Data
=
null
; } } }
And remove the embeded resource “SampleWinApp.frmMain.resources”. after do these, new code is very difficulty to crack.
Additional,If software is design for globalization with multiple UI language,The software will include specify UI language resource dll files.My tools will prompt operator to select a UI language and merge UI language resource data to IL code .and remove embeded .resources file. This will provide a more fast lanuch speed and without UI language resouce dll.
My tool also can change the resource package class code.
For example, This is a resource package class code:
[GeneratedCode
("
System.Resources.Tools.StronglyTypedResourceBuilder"
,"
15.0.0.0"
)] [DebuggerNonUserCode
] [CompilerGenerated
]internal
class
Resource1
{private
static
ResourceManager
resourceMan
;private
static
CultureInfo
resourceCulture
; [EditorBrowsable
(EditorBrowsableState
.Advanced
)]internal
static
ResourceManager
ResourceManager
{get
{if
(resourceMan
==
null
) {ResourceManager
temp
=
resourceMan
=
new
ResourceManager
("
SampleWinApp.Resource1"
,typeof
(Resource1
).Assembly
); }return
resourceMan
; } } [EditorBrowsable
(EditorBrowsableState
.Advanced
)]internal
static
CultureInfo
Culture
{get
{return
resourceCulture
; }set
{resourceCulture
=
value
; } }internal
static
Bitmap
blue96
{get
{object
obj
=
ResourceManager
.GetObject
("
blue96"
,resourceCulture
);return
(Bitmap
)obj
; } }internal
static
string
String2
{get
{return
ResourceManager
.GetString
("
String2"
,resourceCulture
);} }internal
static
string
StringValue
{get
{return
ResourceManager
.GetString
("
StringValue"
,resourceCulture
);} }internal
Resource1
() { } }
After use my tool , It change to :
internal
class
Resource1
{private
static
readonly
byte
[]_Datas
=
_BytesContainer__
._1
();private
static
Bitmap
_blue96
;public
static
Bitmap
get_blue96
() {if
(_blue96
==
null
) {_blue96
=
InnerAssemblyHelper20210315
.GetBitmap
(_Datas
, ,36918
,1807292644
); }return
_blue96
; }internal
static
string
get_String2
() {return
InnerAssemblyHelper20210315
.GetString
(_Datas
,37002
,98
,614997590
); }internal
static
string
get_StringValue
() {return
InnerAssemblyHelper20210315
.GetString
(_Datas
,36918
,84
,57466195
); } }
The resouce data aleady has been encrypted, and hard to crack.
5 ,Hidden allocation call stack.
Hackers can search key information by using memory profiler tools , etc. Scitech .NET memory Profiler.but JieJie.NET can change this stack,puzzle hackers.
For example, I use the follow code to display software license info.
private
void
btnAbout_Click
(object
sender
,EventArgs
e
) {MessageBox
.Show
(this
,GetLicenseMessage
()); }private
string
GetLicenseMessage
() {string
msg
=
"
This software license to :"
+
Environment
.UserName
;return
msg
; }
When you start application in Scitech .NET memory Profiler, and show the about dialog. the screensnapshort like this.
In .NET Memory profiler.the UI is
seach the string "This software license to:Administrator"
and double click , then you can see the follow UI:
There are list the key string value allocation call stack :
mscorlib!System.String.Concat( string,string )
SampleWinApp!SampleWinApp.frmMain.GetLicenseMessage() frmMain.cs
SampleWinApp!SampleWinApp.frmMain.btnAbout_Click( object,EventArgs ) frmMain.cs
System.Windows.Forms!System.Windows.Forms.Control.OnClick( EventArgs )
System.Windows.Forms!System.Windows.Forms.Button.OnMouseUp( MouseEventArgs )
System.Windows.Forms!System.Windows.Forms.Control.WmMouseUp( ref Message,MouseButtons,int )
System.Windows.Forms!System.Windows.Forms.Control.WndProc( ref Message )
System.Windows.Forms!System.Windows.Forms.ButtonBase.WndProc( ref Message )
System.Windows.Forms!System.Windows.Forms.Control.ControlNativeWindow.WndProc( ref Message )
System.Windows.Forms!System.Windows.Forms.NativeWindow.Callback( IntPtr,int,IntPtr,IntPtr )
[Native to managed transition]
[Managed to native transition]
System.Windows.Forms!System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW( ref MSG )
System.Windows.Forms!System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop( int,int,int )
System.Windows.Forms!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner( int,ApplicationContext )
System.Windows.Forms!System.Windows.Forms.Application.ThreadContext.RunMessageLoop( int,ApplicationContext )
SampleWinApp!SampleWinApp.Program.Main() Program.cs
This call stack maby point out how to crack the software.
Then you can change source to :
private
void
btnAbout_Click
(object
sender
,EventArgs
e
) {MessageBox
.Show
(this
,GetLicenseMessage
()); }private
string
GetLicenseMessage
() {var
str
=
"
JIEJIE.NET.SWITCH:+allocationcallstack"
;;//
no used,just let JieJie.NET know the owner method need change.string
msg
=
"
This software license to :"
+
Environment
.UserName
;return
msg
; }
At there,the code var str = "JIEJIE.NET.SWITCH:+allocationcallstack";";
do nothing, just let JieJie.NET know this is a key method, need to change, the value is ignore case.
My tool can change this call stack to this:
mscorlib!System.String.CtorCharArray( char[] )
SampleWinApp2!DCSoft.Common.InnerAssemblyHelper20210315.CloneStringCrossThead_Thread()
mscorlib!System.Threading.ExecutionContext.RunInternal( ExecutionContext,ContextCallback,object,bool )
mscorlib!System.Threading.ExecutionContext.Run( ExecutionContext,ContextCallback,object,bool )
mscorlib!System.Threading.ExecutionContext.Run( ExecutionContext,ContextCallback,object )
mscorlib!System.Threading.ThreadHelper.ThreadStart()
It is more difficuted to find out the key call stack.This feature help you hidden your weakness, protect your software copyright.
6 , Obfuscate class’s members order.
When we write a large class’s code , usual ,field or method for the same target is very nearby.for example:
private
string
_RegisterCode
=
null
;private
bool
_IsRegisteredFlag
=
false
;public
void
SetRegisterCode
(string
code
){};pulbic
bool
IsRegisterdCodeOK
(string
code
){};public
string
GetErrorMessageForRegister
();XXXXXXX
other
members
XXXXXX
When hakers capture one key member,for example _RegisterCode
, and analyse other members nearby, maby can get more information.
But JieJie.NET can obfuscate order of class’s members , just like this:
private
bool
_IsRegisteredFlag
=
false
;XXXXXXX
other
members
XXXXXX
private
string
_RegisterCode
=
null
;XXXXXXX
other
members
XXXXXX
public
string
GetErrorMessageForRegister
();XXXXXXX
other
members
XXXXXX
pulbic
bool
IsRegisterdCodeOK
(string
code
){};XXXXXXX
other
members
XXXXXX
public
void
SetRegisterCode
(string
code
){};XXXXXXX
other
members
XXXXXX
Other members nearby maby have nothing to do with one key member.this can make carck more difficult.
7 , Clean document comment xml file.
JIEJIE.NET can clean document comment xml file. remove member xml element which it renamed.
8 , Save rename map xml file.
JIEJIE.NET can save rename map xml file just like the following:
<dotfuscatorMap
> <header
> <timestamp
>2021-10-23 9:13:25</timestamp
> <product
version
="
1.4.0.1"
user
="
yfyuan"
>JieJie.NET</product
> </header
> <mapping
> <module
> <name
>DCSoft.Writer.ForASPNETCore.dll</name
> <type
> <name
>DCSoft.MyLicense.D8CLicNothing217Helper</name
> <newname
>zzz.z0ZzZzxgk</newname
> <fieldlist
> <field
> <signature
>System.Collections.Generic.Dictionary`2<
object,object>
</signature
> <name
>_Fields</name
> <newname
>z0xjk</newname
> </field
> </fieldlist
> </type
> <type
> <name
>DCSoft.MyLicense.D8CLicNothing063Attribute</name
> <newname
>zzz.z0ZzZzzgk</newname
> </type
> <type
> <name
>DCSoft.Writer.Controls.Web.WebServerCommand</name
> <newname
>zzz.z0ZzZzlfk</newname
> <fieldlist
> <field
> <signature
>string</signature
> <name
>_Description</name
> <newname
>z0zjk</newname
> </field
>
9 , Hidden array define.
People offen define array in source code , for example :
public
static
byte
[]GetBytes
() {return
new
byte
[] {85
,203
,85
,204
,85
,255
,85
,245
,85
,247
,85
,171
,85
,165
,142
,157
,142
,184
}; }
After use JIEJIE.NET, the code change to :
public
static
byte
[]GetBytes
() {byte
[]array
=
new
byte
[18
];InnerAssemblyHelper20211018
.MyInitializeArray
(array
, (RuntimeFieldHandle
)/*
OpCode not supported: LdMemberToken*/
);return
array
; }
10, Encrypt typeof() instruction.
People offen use typeof() instruction to get Type. But this contains some information can used by cracter. JIEJIE.NET can hidden it. For example :
public
static
string
CheckXmlSerialize
() {List
<Type
>rootTypes
=
new
List
<Type
>();rootTypes
.Add
(typeof
(DCSoft
.Writer
.Dom
.XTextDocument
));rootTypes
.Add
(typeof
(DCSoft
.TemperatureChart
.TemperatureDocument
));rootTypes
.Add
(typeof
(DCSoft
.Writer
.Dom
.XTextAccountingNumberElement
));rootTypes
.Add
(typeof
(DCSoft
.Writer
.Dom
.XTextBarcodeFieldElement
));rootTypes
.Add
(typeof
(DCSoft
.Writer
.Dom
.XTextBeanFieldElement
));rootTypes
.Add
(typeof
(DCSoft
.Writer
.Dom
.XTextBlankLineElement
));rootTypes
.Add
(typeof
(DCSoft
.Writer
.Dom
.XTextBlockElement
));rootTypes
.Add
(typeof
(DCSoft
.Writer
.Dom
.XTextBookmark
));rootTypes
.Add
(typeof
(DCSoft
.Writer
.Dom
.XTextButtonElement
));rootTypes
.Add
(typeof
(DCSoft
.Writer
.Dom
.XTextCharElement
));string
result
=
WriterUtils
.CheckXmlName
(rootTypes
);return
result
; }
After use JIEJIE.NET, the code change to :
public
static
string
CheckXmlSerialize
() {List
<Type
>list
=
new
List
<Type
>();list
.Add
(_RuntimeTypeHandleContainer
.GetTypeInstance
(_Int32ValueContainer
._1002_827
));list
.Add
(_RuntimeTypeHandleContainer
.GetTypeInstance
(_Int32ValueContainer
._1964_633
));list
.Add
(_RuntimeTypeHandleContainer
.GetTypeInstance
(_Int32ValueContainer
._4356_95
));list
.Add
(_RuntimeTypeHandleContainer
.GetTypeInstance
(_Int32ValueContainer
._680_162
));list
.Add
(_RuntimeTypeHandleContainer
.GetTypeInstance
(_Int32ValueContainer
._533_68
));list
.Add
(_RuntimeTypeHandleContainer
.GetTypeInstance
(_Int32ValueContainer
._4013_536
));list
.Add
(_RuntimeTypeHandleContainer
.GetTypeInstance
(_Int32ValueContainer
._3964_1144
));list
.Add
(_RuntimeTypeHandleContainer
.GetTypeInstance
(_Int32ValueContainer
._628_824
));list
.Add
(_RuntimeTypeHandleContainer
.GetTypeInstance
(_Int32ValueContainer
._464_234
));list
.Add
(_RuntimeTypeHandleContainer
.GetTypeInstance
(_Int32ValueContainer
._3013_501
));return
WriterUtils
.CheckXmlName
(list
); }
If it work with rename, Cracter is very difficult to find the Type value.
Many information has been hidden.
11 , Encrypt enum values.
Many code whitch call funcions use enum values, for example:
public
Dictionary
<string
,string
>GetAllOptionValues
() {Dictionary
<string
,string
>result
=
new
Dictionary
<string
,string
>();foreach
(PropertyInfo
p
in
this
.GetType
().GetProperties
(BindingFlags
.Public
|
BindingFlags
.Instance
)) {object
v
=
p
.GetValue
(this
,null
);foreach
(PropertyInfo
p2
in
v
.GetType
().GetProperties
(BindingFlags
.Public
|
BindingFlags
.Instance
)) {if
(p2
.CanRead
==
false
||
p2
.CanWrite
==
false
) {continue
; }object
v2
=
p2
.GetValue
(v
,null
);if
(v2
!=
null
) {string
txt
=
v2
.ToString
();if
(v2
is
System
.Drawing
.Color
) {txt
=
XMLSerializeHelper
.ColorToString
((Color
)v2
); }result
[p
.Name
+
'.'
+
p2
.Name
]=
txt
; } }//
foreach }//
foreachreturn
result
; }
After use JIEJIE.NET, It change to:
public
Dictionary
<string
,string
>GetAllOptionValues
() {Dictionary
<string
,string
>result
=
new
Dictionary
<string
,string
>();foreach
(PropertyInfo
p
in
this
.GetType
().GetProperties
((BindingFlags
)_Int32ValueContainer
._22_20
)) {object
v
=
p
.GetValue
(this
,null
);foreach
(PropertyInfo
p2
in
v
.GetType
().GetProperties
((BindingFlags
)_Int32ValueContainer
._22_20
)) {if
(p2
.CanRead
==
false
||
p2
.CanWrite
==
false
) {continue
; }object
v2
=
p2
.GetValue
(v
,null
);if
(v2
!=
null
) {string
txt
=
v2
.ToString
();if
(v2
is
System
.Drawing
.Color
) {txt
=
XMLSerializeHelper
.ColorToString
((Color
)v2
); }result
[p
.Name
+
'.'
+
p2
.Name
]=
txt
; } }//
foreach }//
foreachreturn
result
; }
Some information has been hidden.
12 , Merge assembly files.
When developing , many .NET application split to some assembly files,maby include one exe file and many dll files.
JIEJIE.NET can merge assembly files into a single assembly file.This let application more easy to copy or upgrade.
13 Change target platform
JIEJIE.NET support change .coreflags or .subsystem arguments to change the target platform for result assembly . For example , a .NET assembly is design for x86 , using the following command line:
jiejie.net.exe d:\aa.dll .corflags=0x1
This can modify the result assembly file to x64 platform.
14 , Support .NET Core 3.1
JIEJIE.NET now support .NET Core 3.1.
15 , Easy to use.
My new tool is a .NET framework console application.
It support following command line argument :
input =[required,default argument,Full path of input .NET assembly file , can be .exe or .dll,
currenttly only support .NET framework 2.0 or later]
output=[optional,Full path of output .NET assmebly file , if it is empty , then use input argument value]
snk =[optional,Full path of snk file. It use to add strong name to output assembly file.]
switch=[optional,multi-switch split by ',',also can be define in [System.Reflection.ObfuscationAttribute.Feature].
It support :
+contorlfow = enable obfuscate control flow in method body.
-contorlfow = disable obfuscate control flow in method body.
+/-strings = enable/disable encrypt string value.
+/-resources = enable/disable encrypt resources data.
+/-memberorder = enable/disable member list order in type.
+/-rename = enable/disable rename type or member's name.
+/-allocationcallstack = enable/disable encrypt string value allocation callstack.
]
mapxml=[optional, a file/directory name to save map infomation for class/member's old name and new name in xml format.]
pause =[optional,pause the console after finish process.]
debugmode=[optional,Allow show some debug info text.]
sdkpath=[optional,set the direcotry full name of ildasm.exe.]
prefixfortyperename=[optional, the prefix use to rename type name.]
prefixformemberrename=[optional,the prefix use to rename type's member name.]
deletetempfile=[optional,delete template file after job finshed.default is false.]
merge=[optional,some .net assembly file to merge to the result file. '*' for all referenced assembly files.]
.subsystem=[optional, it a integer value, '2' for application in GUI mode.'3' for application in console mode.]
.corflags=[optional, it is a integer flag,'3' for 32-bit process without strong name signature, '1' for 64-bit wihout strong name, '9' for 32-bit with strong name ,'10' for 64-bit with strong name.]
Example 1, protect d:\a.dll ,this will modify dll file.
>JIEJIE.NET.exe d:\a.dll
Exmaple 2, anlyse d:\a.dll , and write result to another dll file with strong name. enable obfuscate control flow and not encript resources.
>JIEJIE.NET.exe input=d:\a.dll output=d:\publish\a.dll snk=d:\source\company.snk switch=+contorlfow,-resources
So many cool features! But JieJie.NET only has 18000 C# code lines!
So it is small and without any third party component.
In the future
It will support upgrad assembly file from .NET Framework to .NET Core without any source code.Please pay attention to me.
License
JieJie.NET use GPL-2.0 License.
JIEJIE.NET can save tens of thousands of US dollars for your team. so you can donate by paypal , by alipay , by Wechat,help author to feed twins born in 2020.
[NEW] Garma | yyf – Vietnamnhanvan
Sue Hayward, Develop East Arnhem Land, Victoria
Why Garma is important?
“Raising awareness about Indigenous Culture”.
Owen Norris, Djalu, Queensland
Why Garma is important?
“To Support our culture and life style”.
Why I Pledge my support of the Yothu Yindi Foundation
“Because of your support to your culture and future generations.”
Sharing My Memories of Garma
“I lived and enjoyed my experience and journey at the mens master class with Djalu and Milkay”.
Ellen Michel, Victoria
Why Garma is important?
“As a non indigenous person it is a welcome chance to look, listen and to hear: learn more Aboriginal Culture and what it means to be custodians of this land.”
Bill Burdett, Victoria
Why Garma is important?
“Garma is an excellent model which enables attendees to gain a broader and deeper knowledge of the issues involving indigenous Australians”.
My memories of Garma: “Standing in the meal queue and sitting at the communal tables, chatting to other attendees and learning of their reasons for attending Garma; Enjoying the beautiful country in which Garma is located; Participating in group activities; Enjoying excellent coffee!”
Rod Reeve, Northern Territory
My memories of Garma: “The conversations, cultural events, dancing, music, art, friendly people, great food and sensational environment.”
Kate Morgan, New South Wales
Why Garma is important?
“Garma provides a platform for the voices of our Aboiriginal population, and those that want the best for them, coming together for the protection of this countries true heritage and to unite with common passion, care and love of our country and its peoples. The lessons learnt and shared have the opportunity to filter out to a broader population and bring strength to the messages. And so I can come and sit on the side of the bunggul everyday from beginning to end. Bliss.”
Patrick Forman, New South Wales
Why Garma is important?
“Vital role in healing a nation sick at its core.”
Alistair Lee, South Australia
Why I pledge my support to the Yothu Yindi Foundation?
“This (Garma) festival should be on eveyones bucket list.”
Lisa Dhurrkay, Nhulunbuy Northern Territory
Why Garma is important?
“I believe that Garma is important to ALL, Indigenous and non-Indigenous.”
Bianca Williams, Sydney
Why Garma is important?
“Garma is an event that has the ability to change the way people think and feel about Aboriginal Australia. Set amongst the dropback of picturesque Yolngu country in the heart of East Arnhem Land, anyone fortunate enough to attend is encouraged to bring an open heart and mind. Garma will teach you and your organisations how to work better with Aboriginal people whilst also educating younger generations on actualities of our culture, righting the wrongs of fallacies that so strong amongst mainstream Australia.”
Bob Gordon, Tasmania
Why Garma is important?
“It is very difficult for urban Australians to gain an appreciation of Indigenous culture and challenges without a forum like Garma where Yolngu share their culture. Challenging issues are discussed and debated in a spirit of openess and respect.”
Why I pledge my support?
“The bringing together of Indigenous and non-Indigenous Australians to discuss and resolve issues is vitally important to our society. The music, company and bunggul is also great. Spending some time out of the Tasmanian winter is a bonus. ”
Michel Ellen, Victoria
Why Garma is important?
“As a non indigenous person it is a welcome chance to look, listen and to hear: learn more Aboriginal Culture and what it means to be custodians of this land.”
Why I pledge my support?
“Yothu Yindi Foundation stands for ‘Art as Medicine and Message’”
Norris Owen, Queensland
Why Garma is important?
“To Support our culture and life style”
Why I pledge my support?
“Because of your support to your culture and future generations”
Sam Hayward, Victoria
Why Garma is important?
“Raising awareness about Indigenous Culture”
Ndayisenga Clauvis, Australian Capital Territory
Why Garma is important?
“Is important because is an traditional culture”
Why I pledge my support?
“Because I love culture”
Jackie Cesnik, Victoria
Why Garma is important?
“I want to enable First Nations people to be self determined and become leaders in Australia”
Why I pledge my support?
“I think the objectives of the foundation are encouraging young Aboriginal Australians”
Jackie Cesnik, Victoria
Why Garma is important?
“I want to enable First Nations people to be self determined and become leaders in Australia”
Why I pledge my support?
“I think the objectives of the foundation are encouraging young Aboriginal Australians”
Jackie Cesnik, Victoria
Why Garma is important?
“I want to enable First Nations people to be self determined and become leaders in Australia”
Why I pledge my support?
“I think the objectives of the foundation are encouraging young Aboriginal Australians”
Jackie Cesnik, Victoria
Why Garma is important?
“I want to enable First Nations people to be self determined and become leaders in Australia”
Why I pledge my support?
“I think the objectives of the foundation are encouraging young Aboriginal Australians”
Jackie Cesnik, Victoria
Why Garma is important?
“I want to enable First Nations people to be self determined and become leaders in Australia”
Why I pledge my support?
“I think the objectives of the foundation are encouraging young Aboriginal Australians”
Lee Windle, Queensland
Why Garma is important?
Queensland Awareness of the way of life as we should know it!
Why I pledge my support?
To keep the awareness alive in us all.
Suzie Speirs, Victoria
Why Garma is important?
Garma is 100% important for Australian As Mick Dodson said: ‘Australia is nothing without aboriginal recognition We can’t look to the future until we look to the past…we need to move forward together… The speech of Mick Dodsen on open day of Garma 2019 was/ is excellent please make this available Also the speech of yunu Pingu It was all so excellent I would like full script copies of all the great talks at Garma 2019 please.
Why I pledge my support?
For 60 + thousand years indigenous aboriginal people have thrived through sheer will and determination said Mick Dodsen ‘A Treaty will ensure broader population understands what we are…’
Sharing My Memories of Garma
The words spoken by Mick Dodsen by Yunupingu By all the indigenous people who spoke were rich and full and real ‘Australia is nothing without aboriginal recognition We want this to end This is the time.
Sue Moore, Victoria
Why Garma is important?
I think Garma is important to demonstrate the strength of our indigenous culture. The larger it becomes the stronger the argument for representation in the constitution.
Why I pledge my support?
I’m happy to support any and all organisations promoting our indigenous brothers and sisters.
Deb Wadeson, Victoria
Why Garma is important?
I attended Garma with the intention to listen, broaden my knowledge, show my respect and develop my art practice as well as supporting the pathway coordinator of the WARRUWI \Stl Leonard’s College partnership. I think GARMA is important because it shares and celebrates our rich heritage and the wisdom of our First Nations people whilst providing a forum to honestly discuss and confront issues around funding, education, health and politics.
Why I pledge my support?
I pledge my support of the Yothu Yindi foundation because it is a passionate, brave organisation determined to create a united, proud and fair nation where we honour our first peoples and accepts the truth telling that is essential for healing and progress
Sharing My Memories of Garma
The words spoken by Mick Dodsen by Yunupingu By all the indigenous people who spoke were rich and full and real ‘Australia is nothing without aboriginal recognition We want this to end This is the time.
Alisha Fernando, Victoria
Why Garma is important?
Important for firms to learn and understand the connection to people, lands and culture and to learn ways in which to engage and think about their own contribution to reconciliation that is meaningful. The Foundation are doing great work that contributes to the betterment of Australia moving forward
Matt Sykes, Victoria
Why Garma is important?
It is an opportunity for non-Aboriginal Australians to discover a part of our identity that we didn’t even realise was missing. Together we grow stronger and walk towards a better, common future.
Pamela Engelander, Victoria
Why Garma is important?
Joy of sharing time and culture with First Nations people
Oria Wilson, Victoria
Why Garma is important?
To bring people together to understand and experience indigenous culture to share with the world
真正的一打五 没一个能打的
这里是【YYF官方频道】 喜欢YYF的小僵尸们记得点一波订阅哟:https://www.youtube.com/channel/UCSXTYUMDvRiaY0vIZdpHl5Q?sub_confirmation=1
日常更新精彩对黑,激情开黑,刺激单排!
还有各种好玩的RPG小游戏!
นอกจากการดูบทความนี้แล้ว คุณยังสามารถดูข้อมูลที่เป็นประโยชน์อื่นๆ อีกมากมายที่เราให้ไว้ที่นี่: ดูเพิ่มเติม
YoYo Review: YoYoFactory ELEMENT YoYo Review! (*GENTRY STEIN NEW SIGNATURE YOYO!!)
New YoYo Review on the YoYoFactory Element!
BUY THE ELEMENT OR ANY OTHER YOYO HERE! https://www.yoyochampion.com/yoyojoe
Follow me on Instagram! @yoyojoe_1
Business Email: [email protected]
Follow me on TikTok: @yoyojoe_1
~~~~~~~~~~
My Gear:
Canon 80d
24mm 2.8 STM Lens
18135mm USM Zoom Lens
1855mm Kit Zoom Lens
50mm 1.8 STM Lens
GoPro Hero 8
Manfrotto MT290XTA3US 290 Xtra Aluminum Tripod
Manfrotto 502 Video Head MVH502AH
JOBY GorillaPod SLR Zoom
~~~~~~~~~~
~~~~~~~~~~
Editing Software: Adobe Premiere Pro
~~~~~~~~~~
河马的第一次帝国 可能也是最后一次
这里是【YYF官方频道】 喜欢YYF的小僵尸们记得点一波订阅哟:https://www.youtube.com/channel/UCSXTYUMDvRiaY0vIZdpHl5Q?sub_confirmation=1
日常更新精彩对黑,激情开黑,刺激单排!
还有各种好玩的RPG小游戏!
yo yo york as 7 manobras do campeonato
Manobras do campeonato de yo yo
Se inscreva no nosso canal e aprenda muito mais.
https://www.youtube.com/user/igoraboim/videos
Facebook da york https://www.facebook.com/pages/IoioYork/417011668405589
The High Gloss metal Yoyo Unboxing and Review
The High Gloss metal Yoyo Unboxing and Review
To buy or check the product from amazon click below link
https://amzn.to/3pFE3WG
Related video
Swing Swing Amazing Unboxing light Bay blade and Review
https://youtu.be/b611Mhy1sv8
Beyblade Burst Sparking unboxing In Hindi
https://youtu.be/1q53NF1OuSo
30 rupees laser light
https://www.youtube.com/watch?v=NYEMTCBlo7A
3 in 1 Laser Light LED Flashlight UV Torch Infrared Key chain
https://youtu.be/VoIDk54fq1k
Bubble Motion train with amazing lighting and music
https://youtu.be/EjS0RE2IzdQ
Unboxing Super Power Full Green Laser | Class 3 laser light with 10 mW and 532 nm wavelength
https://youtu.be/Vswgc_1Yh1I
นอกจากการดูบทความนี้แล้ว คุณยังสามารถดูข้อมูลที่เป็นประโยชน์อื่นๆ อีกมากมายที่เราให้ไว้ที่นี่: ดูบทความเพิ่มเติมในหมวดหมู่Wiki
ขอบคุณมากสำหรับการดูหัวข้อโพสต์ yyf