quinta-feira, 25 de maio de 2023

Smart Contract Hacking Final Free Chapter - Hacking Games Via Bad Randomness Implementations On The Blockchain

This is our final free chapter in this smart contract hacking series, hopefully you enjoyed it, I am not sure what I am going to work on next, perhaps some malware analysis, reverse engineering or maybe some hacking in the cloud. 

We are currently in 4th quarter and slammed with work so I wouldn't expect any more posts or the full blockchain release till after that eases up.

If you have any questions or comments you can hit us up at: 

@ficti0n

http://cclabs.io 


Cryptographic Implementations and Predictable PRNGs

Within operations that require random values we generally need a form of randomness coupled with our algorithm. If we do not have sufficient randomness and large character sets, we would end up with cryptographic collisions or predictable values depending what we are doing. This Is often the case in video game operations and data security encryption schemes. For example, we do not want to create random values which are predictable and repeatable based on known values or controllable values. With controllable values an attacker could duplicate the value by reverse engineering how it was originally created and what that random seed is. Also, If the value is predictable within a game, we may be able to cheat the game by creating our own valid values that exploit the perceived randomness.

Now we are not going to deep dive into cracking cryptography or brute forcing hash values. First off it takes too much time and effort. Secondly because there are easier more efficient ways of tackling cryptographic issues. Lastly, we do not have time for rabbit holes in a week-long penetration test that require us to explore many other attack vectors. Wasting a whole week on cracking a single cryptographic issue would be a terrible and inefficient penetration test leaving the rest of the target vulnerable. This may be suitable for R&D or a CTF but not for a penetration test.  

What you need to understand is that certain functions often used as randomness on the blockchain is not suitable as a source of randomness. Additionally, understanding how things are implemented will get you much farther when it comes to cryptography then attacking it directly. You do not need to break NSA level encryption by attacking it directly. Instead you should concentrate on finding insecure implementations of these algorithms to get what you need.

Oracle padding attacks are a great example of this if you were in the hacking community back in the late 2000s. The padding attack relied on error messages based on padding within blocks to determine a way to decrypt them. This was a brilliant attack vector as you didn't need to understand deep cryptographic concepts to decrypt data blocks only how blocks work and how it was implemented.  With this knowledge you could leverage the flawed implementation to get the decrypted values.

On the blockchain there are a number of insecure functionality that developers like to use when implementing random values. Most of these are very bad ideas for reasons we will discuss below.  

For Example, the following non-exhaustive but often used list of values are not suitable for randomness within sensitive operations. Usage of these types of values for any sort of calculation is always suspect for closer review:

ü  Secret keys in private variables

ü  Block Timestamps

ü  Block Numbers

ü  Block Hash values

Why you ask? Well regardless of the data being set as private on the blockchain a private variable storage value is 100% readable on the blockchain. There are no secret values. These can be queried as you saw in the storage issues chapter. Also embedding hard coded values are certainly not private as they are in the source code which may be posted directly on the blockchain. Or could be reverse engineered out of the bytecode used to deploy the contract when the source code is not available. If you can get a hold of that value, then you can violate the security of that functionality.

Secondly do not rely on predictable values for randomness especially from block data sources. Block timestamps are controlled by miners which can aid in orchestrated attacks when used as a source of randomness. Also block numbers are easy to query and create predictable attacks when used in calculations, if internal functions are using a block number, they are all using the same PRNG. Finally, block hash values are terrible to use for randomness as only the last 256 block hash values on chain actually have a real value. Anything older than 256 is reduced to 0 meaning that every calculation will use the same value of 0. We will cover that in some of our examples.

This is not an exhaustive list but instead just a small portion of bad decisions for random values. There are plenty of other values which could be used within calculations as a random seed which are also predictable. It is always important to review the data used in these calculations when reviewing smart contract functionality. So, without the need of a PHD in cryptography you should easily discern that all of the above implementation examples are terrible for the inclusion of random data within cryptographic operations.

 

Simple BlockHash Example

Let's start out taking a look at a simple example of using a blockhash value with a blocknumber value. While a hash of a block might seem like a good idea as a random number there are numerous issues with it. Firstly, a blocknumber is a known value set by a miner that persists for a set length of time and can be queried and used in an attacker's similar algorithm to produce the same result and bypass controls. But there is also an underlying vulnerability to this approach when coupled with a blockchash which we will take a look at below.

Action Steps:

ü  Open up your terminal and launch ganache-cli

ü  Type out the code below into Remix

ü  Within the Deploy Environment section dropdown change the JavaScript VM to the web3 Provider option.

ü  Deploy the contract to ganache with the deploy button in Remix

 

 

1.    pragma solidity ^0.6.6;
2.   
3.    contract simpleVulnerableBlockHash {
4.           uint32 public block_number;
5.           bytes32 public myHash;
6.   
7.           function get_block_number() public  {   
8.                   block_number = uint32(block.number);
9.           }
10. 
11.  function set_hash() public{
12.                 myHash = bytes32(blockhash(block_number));
13.         }
14. 
15.  function wasteTime() public{
16.                 uint test = uint(block.number);
17.  }
18. }

 

The simple contract above is querying for the current block number in the get_block_number function on line 8 and storing it within a block_number variable created on line 4.  This is the current block number running on the blockchain.

Then we have a function on line 11 which takes the block number and uses it with the blockhash button to retrieve the blockhash and store it in the myHash variable.

 

BlockHash Vulnerability Walk and Talk:

 

Action Steps:

ü  Execute the get_block_number function

ü  Execute the set_hash function

ü  Check the block_number value

ü  Check the myHash value

ü  Execute the wasteTime function 256 times

ü  Execute the set_hash function

ü  Check your myHash Value

ü  What happened and what implications would this have on calculations your using this value with?

 

So, we have 2 variables of a block number and a block hash associated with that block number. What's the big deal. Well let's walk through this step by step and then play around with the remaining wasteTime function on line 15 to find out.

Starting out if we have the deployed contract and we execute the get_block_number function followed by the set_hash function we will get the following result when checking the block_number and myHash variables.

 


We see the blocknumber of 3 and then a hex value representing the block hash that starts with 0x995f. Now if we were to use this hash as a random value or within some algorithm to create a random value it might work depending what we were doing and the level of security required for the length of time we need it to be perceived as random for. It wouldn't be secure but maybe good enough for your operations.  However, a blockhash has a dark little secret a developer may not be aware of.  Block hashes in Ethereum have short term memory when it comes to blocks older than 256 from the current block.  

So, what happens when we calculate a block after a time lapse? Let's give that a try by executing the wasteTime button till we reach block 259.  Waste time sets a block value and discards it to enumerate blocks for us, it doesn't actually make any real changes. Normally blocks on the Ethereum network enumerate on their own every 30 seconds and we would simply just wait for 256 blocks, but we don't have traffic on our blockchain so we will enumerate it ourselves with wasteTime.

 


After we reach block 259 we execute the set_hash function again which will take block_number of 3 which is older than 256 blocks and get the hash. If you retrieve the myHash variable again after executing the set_hash function again it results in:

 


You will notice the myHash variable is now 0x000. because blocks older than 256 from the current block are not stored and result in a value of 0.  Having a predictable value of 0 in our random algorithm can very likely create a situation where it would be easy to recreate the random number to bypass or cheat functionality in the smart contract.


Video Walkthrough of Bad Randomness:




A classical terrible example is something similar to this.

1.  Function checkWinner() public payable { 
2.     If (blockhash(blockNumber) % 2 == 0) {
3.         Msg.sender.transfer(balance);
4.     }
5.  }

 

In the example above uses a blockhash function with a blockNumber variable within its calculation. The issue with this calculation is if that blockNumber variable is more than 256 blocks old it will return Zero and based on the calculation the user will win every single time.

All the attacker would need to do is play the game to create the blocknumber variable. Then the attacker would simply wait for 256 blocks to pass before checking if he has won the game. By doing this the attacker would guarantee a win. 

 

In order to see how this would work let's take a look at a simple game of chance that implements this concept.

Action Steps:

ü  Type out this code within remix

ü  Deploy the code using Ganache and Web3 options

ü  Try to locate the vulnerability within the code

ü  Try to exploit the vulnerability this code so that you are always the winner

1.  pragma solidity ^0.6.6;
2.   
3.  contract simpleVulnerableBlockHash {
4.      
5.      uint balance = 2 ether;
6.      mapping (address => uint) blockNumber;     
7.      bool public win; 
8.      
9.      constructor() public payable{
10.        require(msg.value >= 10 ether);
11.    }
12.    
13.    function get_block_number() internal  {   
14.        blockNumber[msg.sender] = uint(block.number);
15.    }
16.    
17.    function playGame() public payable {
18.        require (msg.value >= 1 ether);
19.        get_block_number();
20.    }
21.     
22.     
23.    function checkWinner() public payable { 
24.      if (uint(blockhash(blockNumber[msg.sender])) % 2 == 0) {
25.          win = true; 
26.             msg.sender.transfer(balance);
27.      }   else{
28.             win = false;
29.         }
30.    }
31.    
32.}

 After trying to exploit this vulnerability yourself review the following video which walks you through the code and how to exploit it.

Video Walkthrough of Attacking The Game:



 

Preventing Randomness Summary

The best way to prevent these issues is to avoid on chain predictable values or secret values as your seed to operations and calculations.  We can do this with trusted external Oracles.  Oracles are external data sources that your contract can use when it needs random values or trusted data.  There are projects that specifically solve this problem for example ChainLink which has networks of Oracle nodes that handle data queries and provide back trusted verified data including random numbers.  A simple example for using Chainlink for a random number is found at the following link:

https://docs.chain.link/docs/get-a-random-number

It is always a good idea to avoid on chain secret data or block related information when performing any sort of sensitive operation and instead utilize an Oracle.  

 

Bad Randomness References

https://docs.chain.link/docs/get-a-random-number

https://nvd.nist.gov/vuln/detail/CVE-2018-14715
More information

  1. Hack Tool Apk No Root
  2. Hacker Tools Hardware
  3. Hacking Tools For Windows 7
  4. Usb Pentest Tools
  5. Tools Used For Hacking
  6. Hacking Tools Online
  7. Hack App
  8. Pentest Tools Kali Linux
  9. Hack Tools Mac
  10. Pentest Reporting Tools
  11. Tools For Hacker
  12. Termux Hacking Tools 2019
  13. Hack Tools Pc
  14. Hack Website Online Tool
  15. Install Pentest Tools Ubuntu
  16. Hack App
  17. Hack Tools For Ubuntu
  18. Hacking Tools For Games
  19. Pentest Tools Kali Linux
  20. Hacker Tools Linux
  21. Hacker Tools Free
  22. Pentest Tools Online
  23. How To Make Hacking Tools
  24. Tools 4 Hack
  25. Pentest Tools Download
  26. Hacker Techniques Tools And Incident Handling
  27. Hacking Tools For Kali Linux
  28. Pentest Tools Windows
  29. Pentest Tools Review
  30. Hacker Tools Github
  31. Easy Hack Tools
  32. Hacker Tools 2020
  33. Black Hat Hacker Tools
  34. Hacker Tools Apk Download
  35. Hacker Tools For Mac
  36. Hack Tools For Mac
  37. Hack Tools For Games
  38. Pentest Tools Free
  39. Hack Tools Mac
  40. Beginner Hacker Tools
  41. Hacker Tools 2020
  42. What Is Hacking Tools
  43. Usb Pentest Tools
  44. Pentest Tools Linux
  45. Hacker Tools For Pc
  46. Physical Pentest Tools
  47. Pentest Tools Subdomain
  48. Black Hat Hacker Tools
  49. Hack And Tools
  50. Hacking Tools Software
  51. Best Hacking Tools 2020
  52. Pentest Tools Linux
  53. Game Hacking
  54. Nsa Hack Tools Download
  55. Pentest Tools For Ubuntu
  56. Pentest Tools Open Source
  57. What Is Hacking Tools
  58. Pentest Tools List
  59. Pentest Tools Alternative
  60. Pentest Box Tools Download
  61. Hacking Tools Windows 10
  62. Pentest Tools Android
  63. Growth Hacker Tools
  64. Easy Hack Tools
  65. Hacking Tools 2019
  66. Hackrf Tools
  67. Hacker Tools Hardware
  68. Hacking Tools For Windows
  69. Pentest Tools For Ubuntu
  70. Hacks And Tools
  71. Hacking Tools And Software
  72. Hack Tools For Windows
  73. Easy Hack Tools
  74. Pentest Tools Kali Linux
  75. Computer Hacker
  76. Hacking Tools And Software
  77. Usb Pentest Tools
  78. Hacking Tools
  79. Pentest Tools Bluekeep
  80. Hack Tools Download
  81. Hacking Tools For Kali Linux
  82. Nsa Hack Tools
  83. Free Pentest Tools For Windows
  84. Pentest Tools List
  85. Hack Tools 2019
  86. Pentest Tools Linux
  87. Pentest Tools Android
  88. Pentest Tools Find Subdomains
  89. Termux Hacking Tools 2019
  90. Hacking Tools For Windows 7
  91. Pentest Tools Subdomain
  92. Pentest Tools Download
  93. Nsa Hack Tools
  94. Pentest Box Tools Download
  95. How To Hack
  96. Best Hacking Tools 2019
  97. Nsa Hack Tools
  98. Hacking Tools And Software
  99. Hacker Tools Free
  100. Hack Rom Tools
  101. Hacker Tools Apk
  102. Hack Tools For Ubuntu
  103. Hack Tools For Games
  104. Hacking Tools For Kali Linux
  105. Hacker Tools Apk
  106. Pentest Tools Alternative
  107. Nsa Hacker Tools
  108. Hacking Tools For Pc
  109. Hacking Tools 2019
  110. Hacking Tools Name
  111. Growth Hacker Tools
  112. Hack App
  113. Hacking Tools Download
  114. Hackrf Tools
  115. Black Hat Hacker Tools
  116. Hacker Hardware Tools
  117. Hacker Tools Linux
  118. Kik Hack Tools
  119. Hacking Tools For Mac
  120. Hack App
  121. Hack Tools For Mac
  122. Hacker Tools Apk Download
  123. Hacking Tools
  124. Hack Tools
  125. Hack Tools For Ubuntu
  126. Hack Tools Download
  127. Pentest Tools Linux

(22MB) Download Subway Surfers For Free

(22MB) Download Subway Surfers for Free


SCREENSHOT




System Requirements Of Subway Surfers Download For Free

  • Tested on Window 7 64 Bit
  • Operating System: Window XP/ Vista/ Window 7/ Window 8 and 8.1/10
  • CPU: 2.0 GHz Intel Pentium 4 or later
  • RAM: 512 MB
  • Setup size: 22 MB
  • Hard Disk Space: 200 MB









terça-feira, 22 de setembro de 2020

Shantae And The Seven Sirens Review (NSW)

Written by Patrick Orquia


Title: Shantae and the Seven Sirens
Developer: WayForward
Publisher: WayForward
Genre: adventure, platformer, metroidvania
Number of Players: 1
Platform: Nintendo Switch
Release Date: 28 May 2020
Price: $29.99
Also Available On: iOS, Steam, PS4, XB1



Shantae and the Seven Sirens is the newest adventure of the beloved half-genie. I have only played one other game on the series, Shantae and the Pirate's Curse on the 3DS and I love that game and I expected to love this game as well. And I did. In fact, I think this is one of the best games I have played this year. Let me tell you why. 




This game, like the previous games on the series, is of the metroidvania variety, my favorite video game genre as I have mentioned several times on my past reviews. The usual tropes of metroidvania games – exploring interconnected areas, gradual unlocking of abilities, platforming, etc. – are all here, and this game uses these tropes very well.

You play as Shantae, and on this game, she and her usual crew are on vacation in an island to attend the half-genie festival. Shantae along with five other half-genies are set to perform a musical number at the beginning of the festival when tragedy strikes: all of the half-genies, except for Shantae, got kidnapped as their performance begins, and Shantae begins her adventure to free her friends from the clasps of seemingly evil sirens who reside below the island. As you free the other half-genies one by one, they get to lend their abilities to Shantae which makes her transform into different animals, with abilities such as dashing, climbing walls, digging through soil, breaking rocks, swimming, and double jumping. These abilities open up the map gradually as you are able to expore more areas and unlock shortcuts to connect them together, making further exploration and backtracking easier. The game also has warp rooms that make traversing the map much less tedious, as you will be required to go from one end of the map to the other more and more as you progress into the game.




Aside from abilities, you also get to learn dances that act like magic skills. These dances are also learned from the other genie, but you will be required to present them Fusion Stones which you will have to search somewhere in the map. You will be given a clue on where you may find them then it is up to you on how to achieve that. Obtaining most of these Fusion Stones involve sub-quests from other NPCs, which are mostly fetch quests, some will even mark them on the map. Once you solve their sub-quests, you get the Fusion Stones, give it to the half-genie that required them, and you learn their dance. These further unlock areas and treasures and can even be used as wide area attacks that hit all enemies visible on the screen.

If the abilities and dances are still not enough for you, there are also the monster cards that defeated monsters would occasionally drop. These monster cards can be equipped and will give Shantae added buffs, like stonger attacks, faster dash, etc. You can mix and match depending on what you need or your play style. There is a wide variety of enemies in the game and this is a good incentive to defeat every enemy that you face. Defeating enemies doesn't earn you XP, but you get plenty of gems, and with these gems, you can buy upgrades, such as additional weaponry (which themselves can be upgraded to stronger ones) and stronger and faster attacks, in the form of Shantae's long hair. You can also search for and collect heart squids, which can then upgrade your HP. Similar to the Zelda series, you will need four of these to form one new heart container (you have to visit an NPC to do this for you). These heart squids are mostly hidden and often will require you to have already obtained specific abilites to get to them. They are not marked on the map, unfortunately, so you will have to remember where they are so that you can get back to them once you already have the required ability.




The map is divided into different sections which you will unlock the more you explore. With more and more abilities at your disposal, you wil soon find yourself doing more backtracking and having to go from one section to a farther one. Again, the warp rooms can make it easier for you to do this, but if you want to obtain more gems and monster cards, you may want to not use them.

Within some of these map sections lie labyrinths, which act as dungeons. Here, you will encounter lots of enemies, solve some area puzzles, encounter Risky Boots (Shantae's perennial nemesis and act as a mini-boss), and go head to head with sirens: the big baddies of the game. These sirens are huge and have interesting attack patterns and character design, but they are not particularly hard to fight. Their attacks are well-telegraphed and you will easily figure out their patterns. The fight may get finished soon, but you'll have fun the entire time. Upon defeating a boss, the chapter ends and a new one begins. You take your acquired gems to the shop, upgrade your weapons and attacks, and off you go again to explore further to solve the mysteries surrounding the island.




The more you get stronger, the more fun it is to defeat the monsters, and thus, making exploring better. Previously unreachable areas will be eventually reachable, and it is such a good feeling to accomplish that, especially in this game. It may only take you around 10 hours to complete the entire game on your first playthrough, but it is well-paced and very little downtime in action and story elements. There is a New Game+, with Shantae having more magic but less defense. A bit lame, but it could be an extra challenge. If you need more challenge, there are achievements to aim for, such as being able to complete the game on any % items, complete the game with 100%, complete the game at high speed, and complete the game on New Game+. You may need to play the game at least 2 more times to unlock all achievements in the game. You only unlock win screens, though, but that is better than nothing.

Overall, Shantae and the Seven Sirens is one excellent entry to the series. I think Pirate's Curse is a bit better and I did enjoy that game more, but this game is a close second. I should play the other games, to really see which game is the best in the series. Anyway, this game has amazing visuals, cood character design and animation, and solid 60fps framerate mostly throughout the game. Add to that the excellent soundtrack full of catchy tunes that make playing the game even more enjoyable. So if you are a fan of this adorable half-genie, do yourself a favor and go through another big adventure with her. Even if you are not, I'm pretty sure you will enjoy the game, as I did, and this may be one of the best games that you will play this year.



REPLAY VALUE: Very high



PROS
  • Amazing hand-drawn art style with vibrant colors and cool animation
  • Excellent soundtrack, with lots of catchy songs
  • Solid 60fps frame rate mostly thoughout the game
  • Quite a good story, with some twists and turns along the way
  • Wide variety of enemies
  • Cool boss fights, albeit on the easy side
  • Beautiful animated cut scenes with good voice acting
  • The entire game can be finished withing 10-12 hours, but it is well-paced and there is very little down time in terms of action and story elements
  • Humorous dialogue with NPCs
  • Very good use of HD rumble
  • Ideal for handheld gaming
  • Controls are very responsive 

CONS
  • Collectibles are not marked on the map, making backtracking to obtain them a bit tedious especially late in the game
  • Loading times during Transitions in some areas could be a bit too long to be desired
  • New Game+ could have been better


RATING: 4.5/5 hair slashes and belly dances

segunda-feira, 21 de setembro de 2020

Nintendo's 8-Bit Obsession With Golf

Golf is popular in most parts of the world with any concentration of wealth.  It is rather popular in Japan, at least for those who can afford to play it.  Green fees and club memberships are extremely pricey in Japan, so it may not be any surprise that many people who enjoy the game may have to turn to less expensive alternatives to get 18 holes in.  Most video game systems have a golf game, or something intended to resemble golf, released for them.  When Nintendo was releasing early titles for its Famicom, a golf game was a natural addition to its sports library.  But Nintendo kept revisiting the sport with its 8-bit systems, so let's explore how its implementation of golf evolved throughout the 8-bit lifespan.

Read more »

sábado, 12 de setembro de 2020

Discover The White City, Capital Of Arcadia

In Oceanhorn 2: Knights of the Lost Realm, we'll take you to all the main regions of Gaia: Arcadia, Submeria and Pirta. One place you'll get to know well is The White City, and today we'll discuss its history and points of interest.


The White City is the vibrant, rich capital of Arcadia: under the strong leadership of Archimedes, blessed by his continuous scientific breakthroughs, it has prospered and blossomed. After declaring himself Grand Regent, he spent the last 20 years upgrading the pre-existing feudal structures and turning the city into a shining jewel of industrialization; an example for all Gaia to behold.



The city, built by the sea, is an old settlement dating back to the savage wars waged in the name of Sol, Nieto, and Trito. While its feudal walls are ancient, most of the fortifications are of recent build, as is the new city center, developed above Archimedes' modern masterpiece: the Grand Core.

The city is divided into three main districts. Upper Town is where the high society and officers live. Before Archimedes' arrival, the area hosted the Order for All Gods (aka the Mage Guild), whose building is now occupied by the headquarter of Genco Corporation and its automatons workforce. Genco is responsible for the production of appliances and technological artifacts, and as such, it basks in the approving gaze of the Grand Regent. Mages, instead, are banned from the city, and while magic is not explicitly ostracized, few feel comfortable coming forward as users. Upper Town also has access to the railroad, which pierces the town from both East and West.


Lower Town, the area between the Trident fortifications, begins with Genco's loading docks, through which most of the goods come in and leave the White City. The permanent market stalls are a popular attraction, both for visitors and regular citizens. A small slum has spawned not far from the market; despite the efforts of the Grand Regent, the White City cannot embrace all its children, and some less fortunate citizens are forced to seek shelter from the elements under its massive stone arches. Lower Town also used to be the religious district; now, only ruins remain, to remind everyone of the sins committed during the religious strifes of the past.


Past Lower Town, a visitor would soon arrive at the doors of the Knights' Order, the oldest building in town. The palace is one of the few that has maintained its original features, a sign of the importance that the Knights still maintain in Arcadia. The administrative district begins beyond the Order, with offices and business-related infrastructures, such as the airport and the hangars of the Living Fortresses. The entrance of the Grand Core is where the public space runs out, and the influence of Archimedes' Palace, commanding the whole town from the White City's center, becomes predominant.     


Sounds like a place worth visiting? Pack your bags, this year you get to see it with your own eyes!

Austro-Hungarian Vindow Vasher

I finished up the gun barrels and windows this week. Just the funnel, colors and touch ups left to go.

Austro-Hungary Aeronef Fleet Austro-Hungary Novara Class Heavy Destroyer Austro-Hungary Prinz Eugen Class Destroyer

sexta-feira, 4 de setembro de 2020

Kingdom Of Jerusalem Foot Knights


The last of the Foot are done now for my Kingdom of Jerusalem force, this little lot are Foot Knights and are once again from Fireforge Games, this time their Templar Infantry plastic set.


Colours are the same as I have used for my other units in this force, aided greatly by decals from Battle Flag. Basing is 6 figs on a 60 x 50 base and it was a bit of a challenge getting the figs on the bases with the large cloaks that some of the figures in the front rank are wearing.


I've used some of the decals on the rear of the cloaks as well.


I've got a couple of mounted units which will have the same theme and I will start on those soon.


I think the poses in this set are a lot better than the Sergeants set and I quite like the variety I have managed to get in arm positions which gives the unit a more realistic feel. I quite like the faces on the figures, they have really grown on me and my style of painting cam make them quite expressive.


I've got some Irregular Miniatures WW1 Cavalry as a test on the paint table at the moment so will be reporting on those next.