My initial thought was that this was just a question of looking up the right field, but actually it took a bit more digging. If you look at Control in Reflector, you'll see that the Visible property calls GetVisibleCore, which checks an internal state field against the value 2 (which happens to be the constant STATE_VISIBLE).
So in order to find out if a control is visible, we need to locate the state field and do some bit manipulation.
If you have the address of the instance, you can do the following:
.shell -ci "!do <ADDRESS>" grep state (use findstr, if you don't have grep)
The output is something similar to this
0:000> .shell -ci "!do 015892a4" grep state
03aeedcc 400112c 4c System.Int32 1 instance 17432589 state <=== HERE!
03aeedcc 400112d 50 System.Int32 1 instance 2060 state2
049ac32c 40011ef d0 ...lized.BitVector32 1 instance 01589374 state
03aeedcc 40011f0 ad4 System.Int32 1 static 1 stateScalingNeededOnLayout
03aeedcc 40011f1 ad8 System.Int32 1 static 2 stateValidating
03aeedcc 40011f2 adc System.Int32 1 static 4 stateProcessingMnemonic
03aeedcc 40011f3 ae0 System.Int32 1 static 8 stateScalingChild
03aeedcc 40011f4 ae4 System.Int32 1 static 16 stateParentChanged
Notice, that there are two state fields. I haven't looked into why this is the case, but the one you want is the System.Int32. In my example it has a value of 17432589.
The code in GetState is as follows
return ((this.state & flag) != 0);
so all you have to do from here is (17432589 & 2) != 0
and you'll have the Visible state of the specific instance.
Actually, you may have to go a step further. If the above returns false, you need to look up the parent and repeat the trick. For my simple example using a Form that was not necessary.